На главную

Библиотека Интернет Индустрии I2R.ru

Rambler's Top100

Малобюджетные сайты...

Продвижение веб-сайта...

Контент и авторское право...

Забобрить эту страницу! Забобрить! Блог Библиотека Сайтостроительства на toodoo
  Поиск:   
Рассылки для занятых...»
I2R » И2Р Программы » Программирование » VBasic, VBS

BitBlt Tutorial

[введение]

BitBlt - важная часть GDI32 API. Если Вы хотите делать игру, вам просто необходимо научиться переносу битов графического образа (Blit) из-за его быстроты. Знакомство с BitBlt будет хорошей стартовой точкой для изучения DirectDraw. Существует два способа, через которые может быть реализован BitBlt. Есть "Плохой" способ - использовать Picture Box, как область памяти для хранения графического образа, это очень медленный способ. "Хороший" способ - это использовать напрямую зарезервированную область памяти для хранения в ней графики. Это позволяет создавать быструю анимацию без заметных мерцаний. Зарезервированная область памяти называется Memory DC (DC - Device Context - контекст устройства), или просто DC.

Blitting состоит из нескольких шагов:

  1. Создать разные DC для фона, спрайтов, их масок и рабочей области для того чтобы собрать все вместе.
  2. Загрузить фон, спрайты и маски в свои DC
  3. Загрузить фон в DC рабочей области
  4. Загрузить маски в DС рабочей области
  5. Загрузить спрайты в DC рабочей области
  6. Отобразить содержимое DC рабочей области на экран

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

[форма]

Picture1: ScaleMode=Pixel
Timer1: Enabled=False Interval=30

[программа]

Для начала, определим несколько функций. Я рекомендую поместить эти объявления в модуль, так чтобы Вы могли поключить его к проекту, где понадобится BitBlt. Сначала, объявления:

Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

Здесь объявляются функции API, которые мы будем использовать. CreateCompatibleDC создает экземпляр DC, CreateCompatibleBitmap - растрового изображения, DeleteObject и DeleteDC... а вот не скажу! BitBlt получается как сердце, соединяющее все это. Синтаксис BitBlt похож на синтаксис PaintPicture.

Теперь, несколько массивов, костант и объявление типа.

Dim MemHdc() As Long
Dim BitMapHdc() As Long
Dim TrashbmpHdc() As Long
Dim NumOfDcs As Integer

Type tArea
hdc As Long
left As Integer
top As Integer
Width As Integer
Height As Integer
End Type

Public Const SRCAND = &H8800C6
Public Const SRCCOPY = &HCC0020
Public Const SRCINVERT = &H660046

С помощью типа мы сможеи подступиться к нужной области памяти. Константы определяют, каким образом будет скопировано растровое изображение. SRCAND используется для наложения маски. Маска обрезает ненужные пиксели и меняет цвет других так, чтобы вокруг спрайта на фоне не было черного обрамления. SRCINVERT используется для спрайта, а SRCCOPY для загрузки фона и окончания переноса битов. После этого, нам надо создать DС. Я использовал для этого функцию.

Function CreateMemHdc (ScreenHdc As Long, Width As Integer, Height As Integer) As Long

Redim Preserve MemHdc(NumOfDcs)
Redim Preserve BitMapHdc(NumOfDcs)
Redim Preserve TrashbmpHdc(NumOfDcs)

MemHdc(NumOfDcs) = CreateCompatibleDC(ScreenHdc)
If MemHdc(NumOfDcs) Then
BitMapHdc(NumOfDcs) = CreateCompatibleBitmap(ScreenHdc, Width, Height)
If BitMapHdc(NumOfDcs) Then
TrashbmpHdc(NumOfDcs) = SelectObject(MemHdc(NumOfDcs), BitMapHdc(NumOfDcs))
CreateMemHdc(NumOfDcs)
End If
End If
NumOfDcs = NumOfDcs + 1
End Function


Эта функция вызывается позже в программе. Вот место, где рождаются DC! Конечно, создание одних лишь DC без загрузки в них графики - бесполезная трата времени. Вот подпрограмма, которая занимается этим:

Sub LoadBmpToHdc(MHdc As Long, FileN As String)
Dim OrgBmp As Long
OrgBmp = SelectObject(MHdc, LoadPicture(FileN))
If OrgBmp Then
DeleteObject (OrgBmp)
End If
End Sub

Сердце этой подпрограммы - вызов функции SelectObject, которая загружает изображение из файла в созданный DC. Отлично, этот модуль почти сделан, но нам еще понадобится подпрограмма, которая уничтожит все созданные DC, чтобы освободить ОЗУ при выходе из программы.

Sub DestroyHdcs()
Dim i As Integer
For i = 0 To NumOfDcs - 1
BitMapHdc(i) = SelectObject(MemHdc(i), TrashbmpHdc(i))
DeleteObject (BitMapHdc(i))
DeleteDC (MemHdc(i))
Next i
End Sub

Итак, это уже целый модуль. То есть, если вы скопируете его себе, все должно работать (если только нет опечаток, но я вроде проверял). Наконец, настало время писать подпрограммы, которые соберут вместе все вышеупомянутые процедуры и заставят их работать. Снова все по порядку. Сначала секция General:

Dim x As Integer
Dim PicSprite As tArea
Dim PicMask As tArea
Dim PicWork As tArea
Dim PicOrgBack As tArea

Здесь определяются все объекты, использующиеся для адресации наших DC. PicOrgBack - это оригинальный фон, PicSprite и PicMask для спрайта и для маски, PicWork это для DC, где все собирается. Теперь, процедура Form_Load:

Private Sub Form_Load()
Call init
Timer1.Enabled = True
End Sub

Private Sub Form_Unload(Cancel As Integer)
Call DestroyHdcs
End Sub

Здесь вызывается начальная процедура, которая создаст DC:

Sub init()
PicOrgBack.hdc = CreateMemHdc(Picture1.hdc, Picture1.ScaleWidth, Picture1.ScaleHeight)
Call LoadBmpToHdc(PicOrgBack.hdc, app.path & "map1.bmp")

PicSprite.hdc = CreateMemHdc (Picture1.hdc, 77, 63)
Call LoadBmpToHdc (PicSprite.hdc, app.path & "circle2.bmp")

PicMask.hdc = CreateMemHdc (Picture1.hdc, 77, 63)
Call LoadBmpToHdc (PicMask.hdc, app.path & "circle3.bmp")

PicWork.hdc = CreateMemHdc (Picture1.hdc, Picture1.ScaleWidth, Picture1.ScaleHeight)
End Sub

Здесь вызывается CreateMemHdc для создания DC, затем растровые изображения загружаются в свежесозданные DC, за исключением PicWork, так как там мы будем собирать сцену. Для PicSprite и PicMask числа - это реальный размер изображения. Теперь код для элемента Timer, с помощью которого будет создана анимация.

Private Sub Timer1_Timer()
Call screen_refresh
x = x + 25
If x > 300 Then x = 0
End Sub

Таймер вызывает процедуру screen_refresh, которая с помощью переноса битов собирает все вместе и очищает предыдущий экран. Она копирует все в PicWork, а затем перебрасывает его содержимое в PictureBox.

Sub screen_refresh()
BitBlt PicWork.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, PicOrgBack.hdc, 0, 0, SRCCOPY
BitBlt PicWork.hdc, x, 50, 73, 63, PicMask.hdc, 0, 0, SRCAND
BitBlt PicWork.hdc, x, 50, 73, 63, PicSprite.hdc, 0, 0, SRCINVERT
BitBlt Picture1.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, PicWork.hdc, 0, 0, SRCCOPY
End Sub

Сначала фон копируется на рабочую часть. Затем, накладывается маска за ней - спрайт. Наконец, последняя инструкция копирует сцену из памяти на экран.

Попробуйте изменять свойство Inteval у таймера. Такой способ не повлияет на скорость PaintPicture, так как он и так медленный, но при использовании BitBlt вы сразу заметите разницу. Вы можете, а скорее даже нужно заменить объект Таймер циклом. Таймер - очень плохой элемент для анимации из за своих глюков.

Ну вот, это был учебник BitBlt. Если вы запустили программу и удивились - какая разница?! - попробуйте запустить программу, использующую PaintPicture в одном окне, а рядом нашу программу с BitBlt. BitBlt как минимум в три раза быстрее! Я надеюсь, что четко все для вас изложил. Я провел чертовски тяжелое время, добывая хорошую информацию. Примерно 3/4 учебников я написал используя "плохую" технику blitting'а. Я бы никогда не научился blitting'у без Timbo's VB Game Tutorial и программы Tutor2 с Zorro's VB Fun Page.

Peter Kuchnio, перевод Antiloop
VBStreets.ru

Другие разделы
C, C++
Java
PHP
VBasic, VBS
Delphi и Pascal
Новое в разделе
Базы данных
Общие вопросы
Теория программирования и алгоритмы
JavaScript и DHTML
Perl
Python
Active Server Pages
Программирование под Windows
I2R-Журналы
I2R Business
I2R Web Creation
I2R Computer
рассылки библиотеки +
И2Р Программы
Всё о Windows
Программирование
Софт
Мир Linux
Галерея Попова
Каталог I2R
Партнеры
Amicus Studio
NunDesign
Горящие путевки, идеи путешествийMegaTIS.Ru

2000-2008 г.   
Все авторские права соблюдены.
Rambler's Top100