Графика DirectX в Delphi
Шрифт:
Существует одна переменная, связанная с фоном, в нее загружаются различные фрагменты растра:
GameMap := CDXMap.CDXMap(Landscape, GameScreen); // Создание лоскута
GameMap.CreateMap(MapSizeX, MapSizeY, 1) ;
GameMap.MoveTo(0, 0) ; Tile := 1;
for i := 0 to 63 do // Цикл заполнения карты
for j := 0 to 62 do begin // разными фрагментами
GameMap.SetTile (i, j, Tile);
Tile := Tile + 1;
if Tile > 4 then Tile := 1;
end;
Через некоторый
var
Delay : Integer =0; // Счетчик кадров
function TfrmDD.UpdateFrame : HRESULT;
var
wrk : TRECT; // Прямоугольник экрана
i, j, Tile : Integer;
begin
Game Input.Update;
UpdateKeys;
SetRect (wrk, 0, 0, ScreenWidth, ScreenHeight);
// Вывести текущее состояние фона
GameMap.DrawClipped (GameScreen.GetAppBackBuffer, wrk);
Inc (Delay);
if Delay > 40 then begin // Прошло 40 кадров
for i := 0 to 62 do
for j := 0 to 62 do begin
Tile := GaraeMap.GetTile(i, j); // Получить номер фрагмента
Inc (Tile); // Циклический сдвинуть в цепочке фрагментов
if Tile > 4 then Tile := 1;
GameMap.SetTile(i, j, Tile); // Задать новый фрагмент
end;
Delay := 0;
end;
Result := GameScreen.Flip;
end;
Код обработки клавиатуры в примере заметно короче по сравнению с предыдущим:
procedure UpdateKeys;
begin
if KeyDown(DIK_RIGHT) then GameMap.WrapScrollRight(MapScrollSpeed);
if KeyDown(DIK_LEFT) then GameMap.WrapScrollLeft(MapScrollSpeed);
if KeyDown(DIKJJP) then GameMap.WrapScrollUp(MapScrollSpeed);
if KeyDown(DIK_DOWN) then GameMap.WrapScrollDown(MapScrollSpeed);
if KeyDown(DIK_ESCAPE) then frmDD.Close;
end;
На рис. 5.15 запечатлен момент работы нашего очередного примера (проекта каталога Ех16), в котором на экране выводятся координаты пользовательского курсора.
Рис. 5.15. Пример вывода текста и обработки событий мыши
Для изображения курсора предназначена отдельная поверхность, для которой задается ключ:
GameCursor := CDXSurfасе.Create;
GameCursor.CreateCDXSurfaceFromFile(GameScreen,'Cur.bmp');
GameCursor.ColorKey(0);
Для заднего буфера задается конкретный шрифт:
GameScreen.GetAppBackBuffer.ChangeFont('Times', 16, 20, FW_BOLD);
Аналогично процедуре обработки клавиатуры, требуется процедура, связанная с событиями мыши. Обратите внимание,
procedure UpDateMouse;
var
TempX, TempY : Integer;
begin
TempX := GameInput.Mouse.X; // Смещение по осям
TempY := Gamelnput.Mouse.Y;
CurX := CurX + 3 * TempX; // Текущие координаты курсора
CurY := CurY + 3 * TempY;
// Анализ положения курсора вблизи границ экрана
if CurX < 0 then CurX := 0 else
if CurX > ScreenWidth - MapSizeX then CurX := ScreenWidth - MapSizeX;
if CurY < 0 then CurY := 0 else
if CurY > ScreenHeight - MapSizeY then CurY := ScreenHeight - MapSizeY;
if CurX = 0 then begin
if TempX < 0 then GameMap.WrapScrollLeft(-TempX);
end else
if CurX = ScreenWidth - MapSizeX then
if TempX > 0 then GameMap.WrapScrollRight(TempX);
if CurY = 0 then begin
if TempY < 0 then GameMap.WrapScrollUp(-TempY);
end else
if CurY = ScreenHeight - MapSizeY then
if TempY > 0 then GameMap.WrapScrollDown(TempY);
end;
Вывод текста на экран осуществляется с помощью метода TextxY заднего буфера:
function TfrmDD.UpdateFrame : HRESULT;
var
wrk : TRECT;
begin
Gamelnput.Update;
UpdateKeys;
UpdateMouse;
SetRect (wrk, 0, 0, ScreenWidth, ScreenHeight);
GameMap.DrawClipped (GameScreen.GetAppBackBuffer, wrk);
// Вывод курсора
GameCursor.DrawFast(CurX, CurY, GameScreen.GetAppBackBuffer);
// Вьшод текста
GameScreen.GetAppBackBuffer.TextXYUO, 10, 255,
'CDX Example for Delphi');
GameScreen.GetAppBackBuffer.TextXY(10, 30, 255, PChar('X= ' +
IntToStr(CurX))); GameScreen.GetAppBackBuffer.TextXY(10, 50, 255, PChar('Y= ' +
IntToStr(CurY)));
Result := GameScreen.Flip;
end;
Последний пример на эту тему (проект катшюга Ех17) поможет нам разобраться в организации спрайтовой анимации. Здесь вид курсора меняется со временем так, что получается изображение страшного животного, раскрывающего зубастую пасть (рис. 5.16).
Рис. 5.16. При работе примера чудовище раскрывает и закрывает свою пасть
Фазу можно менять, используя метод setTile, как в одном из предыдущих примеров, или же напрямую задавая прямоугольник источника:
Inc (Delay);
if Delay = 10 then begin // Прошло 10 кадров
// Меняем прямоугольник в источнике
SetRect (GameCursor.SrcRect, 39 * wrkl, 0, 39 * (wrkl + 1), 36);
wrkl := (wrkl + 1) mod 3;