InfoCity
InfoCity - виртуальный город компьютерной документации
Реклама на сайте







Размещение сквозной ссылки

 

Часть четвертая: Прибамбасы


Эта часть будет посвящена некоторым методам и приемам, которые могут понадобиться в вашей работе.

Рисование


Вы когда нибудь рисовали на обыкновенном бейсике? Ну помните там всякие команды Line, Circle... и все такое? Так вот, DirectDraw возвращает нас в детский сад и дает набор методов для рисования примитивных геометрических объектов. С другой стороны, это может оказаться очень даже полезно.

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

Private Sub Form_KeyPress(KeyAscii As Integer)
Unload Me 'Выход по нажатию клавиши
End Sub

Private Sub Form_Unload(Cancel As Integer)
mdlDirectDraw7.DestroyDD 'Уходя, гасите свет :)
End Sub

Private Sub Form_Load()
mdlDirectDraw7.CreateDDFullscreen Me.hWnd, 800, 600, 16 'Инициализируем экран
Run 'Подпрограмма рисования
End Sub

Private Sub Run()
DoEvents
Call mdlDirectDraw7.ClearBuffer(ddsBack) 'Чистим полотно

Call ddsBack.SetForeColor(RGB(255, 0, 0)) 'Установить цвет рисования
Call ddsBack.DrawCircle(130, 105, 100) 'Это круг
Call ddsBack.DrawText(100, 100, "Hello, DirectDraw!", False) 'Это текст

Call ddsBack.SetForeColor(RGB(0, 0, 255))
Call ddsBack.DrawLine(250, 30, 500, 30) 'Линии
Call ddsBack.DrawLine(250, 50, 500, 50)
Call ddsBack.DrawLine(250, 70, 500, 70)
Call ddsBack.DrawBox(250, 90, 500, 205) 'Прямоугольник

'Делаем Flip
ddsPrimary.Flip Nothing, DDFLIP_WAIT
End Sub

 

Нахождение доступных видеорежимов


Наверняка вы знаете, что графика - это самая привередливая вещь. На одних компьютерах она может работать прекрасно, на других нет. Одна из частых ошибок, возникающих в программах - это когда они пробуют переключиться в видеорежим, который не поддерживается установленной на компьютере видеокартой. Чтобы пользователь не гадал, почему это супер-навороченная-трехмерно-долбильно-всехктодвижется игрушка вашего производства, помигав экраном, вылетает в систему, вы можете сами сказать ему о том, что его видеокарта не поддерживает трехмерного буфферинга, динамического освещения во внутренних плоскостях, разрешения больше, чем экран монитора и вообще, пусть он выбрасывает ее и покупает Voodoo4.

Но это я так... На самом деле, будет очень полезно, если вы перед тем, как переключиться в графический режим проверите, поддреживается ли он видеокартой пользователя. Также, вы можете перечислить все доступные на компьютере режимы, чтобы потом отобрать нужные вам и показать пользователю для выбора нужного ему. Наверняка вы видели подобное в разных играх, чаще всего в трехмерных бродилках.

Метод GetDisplayModesEnum возвращает объект DirectDrawEnumModes, который содержит в себе доступные видеорежимы. Как их оттуда вытащить? Метод DirectDrawEnumModes.GetCount возвращает количество видеорежимов, а вызов метода DirectDrawEnumModes.GetCount i,ddsd помещате информацию по i-тому режиму в структуру DDSURFASEDESC2 (ddsd), уже знакомую вам по прошлым частям.

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

Создайте проект, нарисуйте форму, а на ней элемент ListBox, который назовите lstModes. Нам не понадобятся ни модуль mdlDirectDraw7, ни библиотека Win32 TLB

Далее, включите в модуль кода формы такую процедуру.

Sub GetDisplayModes()
Dim dd As DirectDraw7
Dim ddsd As DDSURFACEDESC2
Dim DisplayModesEnum As DirectDrawEnumModes
Dim i As Integer

Set dd = dx.DirectDrawCreate("") 'Создать объект DirectDraw
dd.SetCooperativeLevel Me.hWnd, DDSCL_NORMAL 'DirectDraw в окне

Set DisplayModesEnum = dd.GetDisplayModesEnum(0, ddsd) 'Получить объект DirectDrawEnumModes
Dim OutPut As String

'Теперь, методично извлекаем по одному режиму и распечатываем его
For i = 1 To DisplayModesEnum.GetCount()
DisplayModesEnum.GetItem i, ddsd 'Получить описание режима
OutPut = Trim(Str(ddsd.lWidth) & " x" & Str(ddsd.lHeight) & " x" & Str(ddsd.ddpfPixelFormat.lRGBBitCount))
lstModes.AddItem OutPut, 0 'Добавим описание в Лист
Next

Set dd = Nothing 'Убиваем DD
End Sub

Процедура FormLoad элементарна:

Private Sub Form_Load()
Me.Show
GetDisplayModes
End Sub

Возможные применения этой процедуры: вместо ListBox вы можете добавлять найденные режимы в массив, который потом обрабатывать, находя или не находя режимы, нужные для программы, распечатывая их... Фантазия может быть безгранична!

Использование мыши


Вам наверняка мешался в прошлых программах мышиный курсор. Причем на разных компьютерах он мешается по разному. У меня дома он только подмелькивает, а вот у друга его видно всегда. Так вот, покончим с ним раз и на всегда!

Смысл такой: вы рисуете любой курсор в ПайнтБраше и записываете его в формате BMP, после чего создаете оффскринную поверхность, запихиваете туда нарисованный курсор, отслеживаете перемещение мыши и совершаете blitting курсора в текущие координаты мыши. При этом, вам надо жестоко рассправиться с системным курсором - с помощью API функции ShowCursor убрать его с поверхности долой.

Вы можете использовать готовые профессионально нарисованные курсоры, но не забудьте переводить их в формат BMP и рисовать им фон ключевым цветом.

Далее мы внесем некоторые изменения в наш модуль mdlDirectDraw7 для работы с мышью.

Сперва добавьте такие объявления:

Public ddsMouse 'Поверхность для курсоров
Public MouseX As Integer 'Координаты мыши
Public MouseY As Integer

Чтобы прятать, а затем восстанавливать курсор мыши, добавьте в процедуру CreateDDFullscreen строку

Win32.ShowCursor False 'Убить системный курсор

а в процедуру DestroyDD строку

Win32.ShowCursor True 'Восстанавливаем курсор

Теперь, напишем процедуру рисования курсора:

'Рисование указанного курсора мыши с поверхности '=================================================
Public Sub DrawMouse(ByVal MX As Long, ByVal MY As Long, ByVal Size As Long)
rc.Top = MY
rc.Left = MX
rc.Bottom = MY + Size
rc.Right = MX + Size

Call ddsBack.BltFast(MouseX, MouseY, ddsMouse, rc, DDBLTFAST_SRCCOLORKEY Or DDBLTFAST_WAIT)
End Sub

Некоторые пояснения: В процедуре DrawMouse так много параметров для того, чтобы вы могли хранить в буфере несколько курсоров, а потом легко управлять их отображением. Например, если вы хотите сделать анимированный курсор, вы можете сделать счетчик кадров, а потом на основе этого счетчика передавать в процедуру DrawMouse координаты нужного кадра курсора. (MX*i, например). Size нужен для нестандартных курсоров. Система использует курсоры размером 32x32, а вы можете задавать свои курсоры, но они всегда будут квадратными. Не хотите - добавляйте еще параметр.

Подкючение курсора к проекту.

Учтите, что ScaleMode формы должен быть в пикселях (3-Pixel). И вообще, когда работаете с DirectDraw переводите ScaleMode формы в пиксели.

Когда разобрались с формой измерения, добавьте в событие Form_MouseMove две строки:

MouseX = Int(X)
MouseY = Int(Y)

Это будет отслеживать положение мыши и устанавливать новые координаты указателя.

Процедура Form_Load должна выглядеть примерно так:

Private Sub Form_Load()
mdlDirectDraw7.CreateDDFullscreen Me.hWnd, 640, 480, 16 'Инициализируем экран
Set ddsMouse = mdlDirectDraw7.CreateDDSFromFile(App.Path & "\cursor.bmp")
mdlDirectDraw7.Running = True
Run 'Подпрограмма рисования
End Sub

Теперь, напишем подпрограмму Run:

Private Sub Run()
Do While mdlDirectDraw7.Running = True
DoEvents
Call mdlDirectDraw7.ClearBuffer(ddsBack) 'Чистим полотно
Call ddsBack.SetForeColor(RGB(255, 0, 0)) 'Установить цвет рисования

Call ddsBack.DrawText(100, 100, "Этот пример показывает как использовать", False) 'Это текст
Call ddsBack.DrawText(100, 120, "собственные курсоры в DirectDraw!", False)
Call ddsBack.DrawText(100, 200, mdlDirectDraw7.MouseX & " " & mdlDirectDraw7.MouseY, False) 'Отображаем координаты мыши

mdlDirectDraw7.DrawMouse 0, 0, 32 'Рисуем мышь

'Делаем Flip ddsPrimary.Flip Nothing, DDFLIP_WAIT
Loop
Unload Me
End Sub

Чтобы выйти из программы, потребуются еще две процедуры

Private Sub Form_KeyPress(KeyAscii As Integer)
mdlDirectDraw7.Running = False 'Выход по нажатию клавиши
End Sub

Private Sub Form_Unload(Cancel As Integer)
mdlDirectDraw7.DestroyDD 'Уходя, гасите свет
End Sub

Теперь, если ничего не забыли, программа должна работать. Ура!

Frames Per Second


Полезный и очень часто используемый прибамбас - счетчик количества выведенных кадров в секунду (FPS). Чтобы потом не отвлекаться на него, допишем в модуль mdlDirectX процедуру, которая будет выводить его в указанном месте.

Добавьте в Declarations модуля такие определения

'FPS
Private count As Integer
Private tLast As Single
Private fps As Single

Теперь, сама процедура вывода счетчика:

'Рисование счетчика количества кадров в секунду '================================================
Public Sub DrawFPS(ByVal X As Long, ByVal Y As Long)
Dim tcolor As Long

If count = 30 Then
If tLast <> 0 Then fps = 30 / (Timer - tLast)
tLast = Timer
count = 0
End If
count = count + 1
tcolor = ddsBack.GetForeColor 'Чтобы не влиять потом на установленный цвет
Call ddsBack.SetForeColor(RGB(255, 255, 255))
Call ddsBack.DrawText(X, Y, "Frames per Second " & Format$(fps, "#.0"), False)
Call ddsBack.SetForeColor(tcolor)
End Sub

Для примера, подключите счетчик кадров в прошлом проекте (с мышью) перед выводом курсора с помощью такой строчки:

mdlDirectDraw7.DrawFPS 10, 10

Если заработает (а должен заработать!) попробуйте изменять видеорежимы. У меня уже на 800x600x24 было 14 кадров, а в 800x600x8 счетчик "зашкалило" т.е. он вышел за пределы частоты обновления экрана.

 

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

В следующей главе будет разбираться оконный режим DirectDraw.

[Назад][Вперед]


Реклама на InfoCity

Яндекс цитирования



Финансы: форекс для тебя








1999-2009 © InfoCity.kiev.ua