Мир программирования

 


Найти: на:


Меню
Партнеры
Счетчики
Реклама

Direct Draw по русски
Эффекты мультипликации


Теперь мы с Вами перейдем к тому, ради чего собственно и затеяли всю эту бодягу с программированием при помощи DirectDraw. Мы с Вами рассмотрим основы эффекта мультипликации. Как Вам (я надеюсь) известно сам эффект мультипликации состоит в быстрой смене кадров. Все движения персонажа заранее нарисованы, расположены в определенном порядке и сохранены в растровом файле. При создании спрайтов можно поступить по разному. Можно создать один файл (большой) в котором сверху нарисовать фон, а внизу расположить все спрайты. Мы, для удобства поступим так. Чтобы нам не загружать несколько файлов, а следовательно экономить время, создадим файл, размером 640х544 в котором верхняя часть размером 640х480 будет представлять собой некий фон, а оставшаяся часть вполне пригодна для размещения 10 кадров, размером 64х64 - это и буду спрайты. Далее должны создать третью поверхность, которая содержала бы нашу картинку вместе с фоном и спрайтами. Для этого нужно опять же в разделе объявления переменных var объявить её родную.

var

. . . . .

SpriteSurface : IDirectDrawSurface;

. . . .

С этой самой поверхности мы будем копировать нужные участки (rectangle) изображения на вторичную поверхность в определенном порядке. Порядок прост. Сначала мы копируем фоновое изображение, а затем накладываем поверх него спрайтовое изображение. Из этого делаем вывод, что нам также потребуется переменная типа TRect. Мы не долго думая объявляем таковую.

. . .

Rect: TRect;

. . .

Что же нам нужно ещё, для того, чтобы получить эффект мультипликации? Конечно же счетчик кадров, который будет гонять по кругу наши 10 картинок. Чтобы гонять с определенной скоростью, можно процедуру обновления экрана RedrawScreen (так мы её назовем) обрабатывать в событии OnTimer стандартного таймера Delphi, создав его предварительно. Но по моему лучше воспользоваться функцией GetTickCount, так как она работает стабильнее. Исходя из этого нам потребуются еще две переменные, типа DWORD. Обзовем их CurrentTick и LastTick. Время задержки обновления экрана будем находить из разницы между CurrentTick - LastTick. Каждый тик происходит примерно за 55 мс, что достаточно быстро для нас. Вот тут-то мы и введем еще одну переменную, которая будет определять скорость, или задержку смены экрана. Обзовем её Delay (задержка). Эта переменная имеет простой тип Integer. Так давайте сделаем это.

var

. . . .

CurrentTick, LastTick : DWord;

Delay, Frame: Integer; //Объявили задержку и счетчик кадров

. . .

Давайте теперь создадим поверхность SpriteSurface.

begin

. . . . .

with SurfaceDescription do begin

dwSize := sizeof(SurfaceDescription);

dwFlags := ddsd_caps or ddsd_height or ddsd_width;

ddsCaps.dwCaps:=ddscaps_offscreenplain;// говорит о том, что поверхность является вне экранной

dwwidth:=640;

dwheight:=544;

end;

DDResult:=DDrawObject.CreateSurface(SurfaceDescription,SpriteSurface, nil);

. . . . .

end.

Теперь попробуем написать процедуру перерисовки экрана.

procedure RedrawScreen;

begin

CurrentTick :=GetTickCount; // Берем значение нового тика

if CurrentTick - LastTick > Delay then begin // вычислили задержку смены кадра

LastTick := CurrentTick; // Сравняли значения

Rect.Top :=0;

Rect.Left :=0;

Rect.Right :=640;

Rect.Bottom :=480;

//Описали область, копируемую в качестве фона

DDResult:=SecondarySurface.BltFast(0,0,SpriteSurface,Rect,DDBLTFAST_NOCOLORKEY+DDBLTFAST_WAIT);

{Осуществили переброс изображения с поверхности SpriteSurface с началом в точке 0,0 и используя область описанную переменной Rect. Обратите внимание на флаги. Флаг DDBLTFAST_NOCOLORKEY копирует изображение как оно есть, а флаг DDBLTFAST_WAIT говорит о том, что обновление синхронизируется с обратным вертикальным ходом луча, чем и достигается отсутствие мерцаний изображения. Теперь нам нужно нарисовать поверх фона кадр изображения. Сначала мы описываем перебрасываемую область.}

Rect.Top :=480;

Rect.Left :=Frame;

Rect.Right :=Frame+64;

Rect.Bottom :=Rect.Top+64;

// Перебрасываем изображение

DDResult:=SecondarySurface.BltFast(288,208,SpriteSurface,Rect,DDBLTFAST_NOCOLORKEY+DDBLTFAST_WAIT);

// Далее вычисляем следующий кадр

Frame := Frame+64;

// И наконец зацикливаем смену кадров

if Frame >=576 then Frame :=0;

// И наконец пишем функцию Flip

DDResult:=PrimarySurface.Flip(nil,ddFlip_Wait);

end;

end;

Самое главное - не забыть включить в процедуру FreeAll еще две строчки.

procedure FreeAll;

begin

DDrawObject.RestoreDisplayMode;

SecondarySurface._Release;

pointer(SecondarySurface):=nil;

PrimarySurface._Release;

pointer(PrimarySurface):=nil;

SpriteSurface._Release;

pointer(SpriteSurface):=nil;

DDrawObject._Release;

pointer(DDrawObject):=nil;

end;

Добавьте эту процедуру в цикл опроса сообщений от системы, что в самом конце программы.

Теперь запустите программку. И посмотрите, что у Вас получилось...

Продолжение здесь.

Опрос

Конкурсы
Реклама

 

Web дизайн: Бурлаков Михаил    

Web программирование: Бурлаков Михаил

Используются технологии uCoz