Дата публикации статьи: 10.07.2003 00:00
Сегодня мы будем изучать самую главную часть DirectX - DirectDraw, которая отвечает
за 2D-графику. Как всегда нам потребуются библиотеки DirectX версии 7(не SDK)
или выше. Стащить можно прямо с {сайта
Microsoft}.
После данной нехитрой операции можно приступать к программированию. Загрузим Visual
Basic, создадим новый проект (Standard EXE). Подключим библиотеки DirectX к проекту:
"Project - References - DirectX 7 for Visual Basic Type library". Теперь
можно приступить к написанию программного кода:
Объявим в General Declarations формы:
Dim dx as New DirectX7 'объявляем об использовании DirectX7
Dim dd As DirectDraw7 'объявляем об использовании DirectDraw7.
!!! DirectX7 является последней версией на момент написания статьи. Возможно,
что мой читатель располагает более поздней версией DirectX и тогда он будет
объявляеть Dim dd as DirectDraw8 и т.п. !!!
Создадим несколько, так называемых "поверхностей" (surfaces). Поверхности
Primary и Back будут служебными, их мы будем использовать для создания back
buffer'а (обратного буфера). Intro будет использоваться для создания фона, а
Sprites для объекта. Также мы будем использовать ddsd1 и ddsd2 - шаблоны-дескрипторы,
которые устанавливают свойства выводимых данных.
Dim Primary As DirectDrawSurface7
Dim Back As DirectDrawSurface7
Dim Intro As DirectDrawSurface7
Dim Sprites As DirectDrawSurface7
Dim ddsd1 As DDSURFACEDESC2
Dim ddsd2 As DDSURFACEDESC2
!!! Аналогичная история с версиями DirectX !!!
Перед инициализацией неплохо бы написать модуль, который показывал/скрывал
курсор мышки. Далее приведён именно он:
Declare Function ShowCursor Lib "User32" (ByVal bShow As Long) As
Long 'API функция для показа/скрытия курсора
Public lShowCursor As Long 'служебные
Public lRet As Long 'переменные
Public Sub HideMouse() 'Sub, который прячет курсор
Do
lShowCursor = lShowCursor - 1
lRet = ShowCursor(False)
Loop Until lRet < 0
End Sub
Public Sub ShowMouse() 'Sub, который показывет курсор
Do
lShowCursor = lShowCursor - 1
lRet = ShowCursor(True)
Loop Until lRet >= 0
End Sub
Теперь можно приступить к процессу инициализации DirectDraw. Напишем специальный
Sub для этого:
Sub Init()
On Local Error GoTo errOut 'если происходит ошибка в ходе выполнения всего этого
безобразия идём к процессу очистки памяти
Call HideMouse 'скрываем курсор, чтобы не мешал
Наполняем переменную dd смыслом её жизни:
Set dd = dx.DirectDrawCreate("")
Только потом показываем форму, а не наоборот!
Form1.Show
Теперь укажем режим работы. В следующем примере используется разрешение 640x480,
16 разрядов цветов, полноэкранный, расширенный режим. Можно, конечно же, работать
и в оконном (DDSCL_NORMAL), но производительность тогда заметно падает. Работа
в VGA режиме (DDSDM_STANDARDVGAMODE) нынче тоже совсем не нужна...
!!! Если вы хотите использовать 256 цветов, тогда пишите Call dd.SetDisplayMode(640
, 480, 8, 0, DDSDM_DEFAULT) !!!
Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_FULLSCREEN Or DDSCL_EXCLUSIVE)
Call dd.SetDisplayMode(640, 480, 16, 0, DDSDM_DEFAULT)
Установим флажки к дескриптору поверхности Primary.
ddsd1.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
ddsd1.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or DDSCAPS_FLIP Or DDSCAPS_COMPLEX
ddsd1.lBackBufferCount = 1
Устанавливаем параметры поверхности Primary из уже готового шаблона-дескриптора
ddsd1.
Set Primary = dd.CreateSurface(ddsd1)
Наполняем back buffer из уже подготовленной поверхности Primary:
Dim caps As DDSCAPS2
caps.lCaps = DDSCAPS_BACKBUFFER
Set Back = Primary.GetAttachedSurface(caps)
Загружем картинку в поверхность Intro, используя дескриптор ddsd2, для использования
её, как фона. Предварительно неплохо бы иметь файл background.bmp в директории
проекта.
ddsd2.lFlags = DDSD_CAPS
ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
Set Intro = dd.CreateSurfaceFromFile("background.bmp", ddsd2)
Заполним поверхность Sprites из файла sprites.bmp. Дескриптор тот же, т.е.
ddsd2. Обратите внимания на то, что я добавил ещё параметры IHeight и IWidth.
Его следует использовать, если размер заготовленной картинки меньше размеров,
объявленных в dd.SetDisplayMode. В данном случае высота у моей картинки равна
32 пикселям (IHeight), и ширина равна 32 пикселям (IWidht). Если размеры картинки
равны объявленным в dd.SetDisplayMode, то IHeight и IWidth можно не указывать.
Если бы у меня длина картинки была бы равна указанной в dd.SetDisplayMode, то
я бы IWidth и не писал бы.
ddsd2.lHeight = 32
ddsd2.lWidth = 32
Set Sprites = dd.CreateSurfaceFromFile("sprites.bmp ", ddsd2)
Объявим переменную key, как DDCOLORKEY и укажем ей границу DirectDraw-цвета
от 0 до 0. Это означает, что цветом для прозрачности будет абсолютно чёрный.
Можно указывать несколько цветов, например от 0 до 10 и т.д.
Dim key As DDCOLORKEY
key.low = 0
key.high = 0
Sprites.SetColorKey DDCKEY_SRCBLT, key
Рисуем спрайты при помощи следующих команд. Их содержимое рассматривается далее.
UpdateBack
UpdateObject
errOut:
CleanUp
!! Процедуру CleanUp надо добавить и в form_unload !!
End Sub
Создадим процедуру UpdateObject, которая будет обновлять объект.
Sub UpdateObject()
Dim ddrval As Long 'буфер для прорисовки спрайта.
Dim rcRect As RECT 'тип данных, задающий позицию спрайта
Позиции объекта в графическом файле (sprites.bmp) (Left - слева, Top - сверху,
Right - справа, Buttom - снизу)
rcRect.Left = 0
rcRect.Top = 0
rcRect.Right = 32
rcRect.Bottom = 32
x=0
y=0
Для анимации спрайтов лучше всего использовать метод BltFast. Мы рисуем его
на поверхности Back. Переменные x и y - место расположение спрайта на форме.
ddrval = Back.BltFast(x, y, Sprites, rcRect, DDBLTFAST_SRCCOLORKEY Or DDBLTFAST_WAIT)
End Sub
Следующий Sub используется для отрисовки фона:
Sub UpdateBack()
Dim rcRect As RECT 'уже знакомые нам переменные
Dim ddrval As Long
Размер фона 640x480:
rcRect.Left = 0
rcRect.Top = 0
rcRect.Right = 640
rcRect.Bottom = 480
Теперь рисуем используя картинку, загруженную в поверхность Intro:
ddrval = Back.BltFast(0, 0, Intro, rcRect, DDBLTFAST_NOCOLORKEY Or DDBLTFAST_WAIT)
End Sub
И последний Sub: расчистка, который показывает мышь и восстанавливает видео-режим.
Sub CleanUp()
Call ShowMouse
Call dd.RestoreDisplayMode
Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)
End
End Sub
|