Дата публикации статьи: 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