DirectX & Visual Basic

Основные приёмы работы с Direct3d

Здесь описаны некоторые приёмы, которые могут понадобиться Вам при работе с Direct3d.

Полноэкранный режим

Большая часть игр работает в полноэкранном режиме, мы же в предыдущих статьях рассматривали лишь окнный режим Direct3d. Для работы в полноэкранном режиме недостаточно лишь изменить свойство Windowed объекта d3dpp, необходимого при создании устройства Direct3d, на False. Нужно также изменить свойства этого объекта BackBufferHeight и BackBufferWidth на нужную высоту и ширину экрана в пикселах соответственно. Чтобы всё было окончательно понятно, смотрите пример:

'В этом примере DX - объявленный объект DirectX8
'D3D - объект Direct3D8
'D3DDevice - объект Direct3DDevice8
Public Function InitD3d(hWnd As Long) As Boolean
On Local Error Resume Next

Set D3D = DX.Direct3DCreate()

Dim Mode As D3DDISPLAYMODE
D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, Mode

Dim d3dpp As D3DPRESENT_PARAMETERS
d3dpp.Windowed = False
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC
d3dpp.BackBufferFormat = Mode.Format
d3dpp.BackBufferCount = 1
d3dpp.BackBufferHeight = Mode.Height
d3dpp.BackBufferWidth = Mode.Width
d3dpp.EnableAutoDepthStencil = 1
d3dpp.AutoDepthStencilFormat = D3DFMT_D16

Set D3DDevice = D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, _
                                     D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp)
If D3DDevice Is Nothing Then Exit Function

D3DDevice.SetRenderState D3DRS_ZENABLE, 1

InitD3d = True
End Function

Как видите, в этом примере разрешение экрана установливается такое же, как и у рабочего стола, что гарантирует то, что данный режим поддерживается видеокартой пользователя.

Доступные видеорежимы

Часто бывает полезно знать, какие видеорежимы поддерживаются видеокартой пользователя, чтобы затем использовать эту информацию при инициализации Direct3d. Посмотрите на код процедуры ShowModes, которая выводит все режимы экрана, поддерживающиеся Вашей видеокартой.

'создайте новый проект
'подключите к нему библиотеку DirectX 8 for Visual Basic Type Library
'на форму добавьте элемент управления ListBox с именем List1
'сделайте следующие объявления:
'Dim DX As New DirectX8
'Dim D3D As Direct3D8
'в процедуру Form_Load добавьте вызов процедуры ShowModes
Public Sub ShowModes()
Dim kModes As Integer
Dim i As Integer
Dim Mode As D3DDISPLAYMODE

Set D3D = DX.Direct3DCreate()

kModes = D3D.GetAdapterModeCount(D3DADAPTER_DEFAULT)
For i = 0 To kModes - 1
 D3D.EnumAdapterModes D3DADAPTER_DEFAULT, i, Mode
 List1.AddItem Str(Mode.Width) & "x" & Str(Mode.Height)
Next
End Sub

Если Вы сделаете всё так, как написано в комментарии и запустите программу на исполнение, то в списке List1 Вы увидите режимы экрана, поддерживаемые Вашей видеокартой. Моя видеокарта, как оказалось, поддерживает 11 режимов от 320x200 до 1024x768.

Удаление указателя мыши

Как правило, в программах и играх, работающих в полноэкранном режиме указатель мыши не используется. Чтобы он не мешал, его просто удаляют с экрана, когда же программа завершает работу и появляется рабочий стол, указатель мыши опять выводят на экран. Делается это с помощью функции ShowCursor из Win32 API. Для того, чтобы Вы могли использовать эту функцию её надо сначала объявить, как показано ниже.

Public Declare Function ShowCursor Lib "user32" (ByVal bShow As Long) As Long

Теперь, для того, чтобы убрать указатель мыши с экрана, достаточно одной строки кода, а именно:

ShowCursor False

Когда же Вам потребуется опять показать указатель мыши на экране, Вы можете использовать ту же функцию, но с параметром True. Код, убирающий указатель мыши с экрана можно вставить, например, в функцию InitD3d, а возвращающий его обратно, в процедуру CleanUp.

Вывод текста

В программах часто появляется потребность в выводе текста на экран, например, если в игре Вам надо показать счёт или количество оставшихся патронов. Деляется это с помощью класса D3DXFont. Инициализация объектов этого класса проходит так, как показано ниже:

'В этом примере GameFont - объект D3DXFont
'D3DX - объект D3DX8
'D3DDevice - объект Direct3DDevice8
Public Sub InitGameFont()
Dim MyFont As IFont
Set MyFont = New StdFont
MyFont.Name = "Arial cir"
MyFont.Size = 15
MyFont.Bold = True
Set GameFont = D3DX.CreateFont(D3DDevice, MyFont.hFont)
End Sub

Если Вы хотите выводить на экран символы кириллицы, то не забудьте прибавить к названию шрифта "cir".

Код, выводящий текст на экран должен быть расположен между методами BeginScene и EndScene устройства рендеринга, указанного в первом параметре метода CreateFont объекта D3DX. Кроме того перед выводом текста нужно произвести вызов метода Begin объета класса D3DXFont, а после - вызов метода End. Для вывода текста на экран можно использовать, например, такую процедуру:

Public Sub DrawText(sString As String, tX As Long, tY As Long)
Dim rcText As RECT
With rcText
.Left = tX
.Top = tY
End With

GameFont.DrawTextW sString, Len(sString), rcText, 0, &HFFFFFFFF
End Sub

Как видите, непосредственно для рисвония текста используется метод DrawTextW объекта GameFont. Последний его параметр - цвет рисуемого текста (в данном примере - белый). Вы можете добавить параметр color в процедуру DrawText, чтобы рисовать текст разного цвета.

Ниже приведён пример кода, который Вы можете вставить в процедуру Render Вашей программы между методами BeginScene и EndScene.

GameFont.Begin
DrawText "Привет всем!!!", 5, 5
GameFont.End

Замечу также, что без методов Begin и End объекта GameFont можно было бы и обойтись.

Программирование главного игрового цикла

Если Вы решили сделать трёхмерную игру, то, какого бы жанра она не была, без главного игрового цикла Вам не обойтись. Что же это такое? Попробую объяснить на примере.

Ранее, в учебнике DirectX Graphics, нами для вызова рендеринга объектов в новом положении использовался элемент управления Timer. Однако, при создании игр, тем более работающих в полноэкранном режиме, эта методика не подходит из-за слишком маленькой скорости обновления экрана. В таких случаях поступают, как показано ниже:

'для использования этого примера
'необхдимо объявить переменную 
'IsRunning типа Boolean
Private Sub Form_Load()

Me.Show
IsRunning = True

If Not InitD3d(Me.hWnd) Then
   MsgBox "Ошибка инициализации Direct3d.", vbCritical, "Ошибка"
   End
End If

InitGeometry

Do While IsRunning
   DoEvents
   'Необходимо использовать внутри
   'главного игрового цикла функцию DoEvents,
   'иначе программа просто вызовет зависание компьютера
   RenderScene
Loop

CleanUp
End

End Sub

Переменная IsRunning должна быть видна во всей программе (испольуйте Public для её объявления). Для выхода из программы, построенной на основе главного игрового цикла, используется такой код:

IsRunning = False

Думаю, теперь всё должно быть ясно.

Подсчёт количества кадров в секунду

Подсчёт количества кадров в секунду или, по-английски, Frames Per Second (FPS) - дело очень важное и полезное. Ведь, как известно, человеческий глаз воспринимает картинку как движущуюся, только если она изменяется чаще чем 25 раз в секунду. А вообще, чем FPS больше, тем лучше. Ниже Вы можете видеть код процедуры ComputeFPS (вызов этой процедуры должен производиться внутри главного игрового цикла), которая, как следует из её названия, занимается подсчётом FPS.

'для использования этой процедуры
'сделайте следующие объявления:
'Public fpsCount As Integer
'Public fpsTLast As Single
'Public FPS As Single
Public Sub ComputeFPS()
fpsCount = fpsCount + 1
If fpsCount = 50 Then
 FPS = 50 / (Timer - fpsTLast)
 fpsTLast = Timer
 fpsCount = 0
End If
End Sub

Вычисленное этой функцией FPS можно вывести на экран с помощью такого кода:

'см. "Вывод текста"
DrawText Str(FPS), 5, 5

Заключение

Здесь, конечно, описана лишь малая часть возможностей DirectX Graphics. Некоторые из описанных здесь возможностей реализованы в первой моей 3d игре "Пинг-понг". Вы можете скачать архив RAR с проектом Visual Basic и файлами .X, использующимися в этой программе, для того чтобы увидеть, как описанные здесь приёмы работы с Direct3d используются на практике. Теперь, я думаю, у Вас достаточно знаний чтобы написать собственную простенькую 3d игрушку на Visual Basic.

Hosted by uCoz