Пишем первую игру
Разработка первой игры - ключевой момент для любого программиста, работающего с графикой. В этой статье мы попробуем это сделать с помощью библиотеки DirectX.
Разработка первой игры — ключевой момент для любого программиста, работающего с графикой. При создании игры мы будем использовать библиотеку DirectX. Наше первое творение будет представлять простой пример полета самолета, однако, если вы не сможете разобраться в принципе работы этой программы, вам будет довольно трудно в разработке более сложных игр. Этот пример, выбран не случайно, в нем рассматриваются базовые приемы работы с графикой.
Начало работы
Прежде чем начать работу, убедитесь, что у вас установлена версия DirectX 7.0 или более поздняя. Думаю, это не проблема, если у Вас на данный момент не установлена нужная версия, во многих сборниках программного обеспечения можно найти нужную версию продукта. Я бы посоветовал установить DirectX 8. Также необходима пятая или более поздняя версия пакета Delphi. В данной статье мы не станем рассматривать весь код программы полностью, так что если бы вы захотели бы посмотреть программы в действии, то скачайте ее прямо отсюда flight.zip . После того как все сделано, можно переходить непосредственно к написанию программного кода.
Разработка игры
...
1. hRet := DirectDrawCreateEx (nil, FDD, IDirectDraw7, nil);
2. if Failed (hRet) then ErrorOut(hRet, 'DirectDrawCreateEx');
3. hRet := FDD.SetCooperativeLevel(Handle, DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE);
4. if Failed (hRet) then ErrorOut(hRet, 'SetCooperativeLevel');
5. hRet := FDD.SetDisplayMode (640, 480, 16, 0, 0);
6. if Failed (hRet) then ErrorOut(hRet, 'SetDisplayMode');
7. ZeroMemory(@ddsd, SizeOf(ddsd));
8. with ddsd do begin
9. dwSize := SizeOf(ddsd);
10. dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
11. ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE or DDSCAPS_FLIP or DDSCAPS_COMPLEX;
12. dwBackBufferCount := 1;
13. end;
14. hRet := FDD.CreateSurface(ddsd, FDDSPrimary, nil);
15. if Failed (hRet) then ErrorOut(hRet, 'Create Primary Surface');
16. ZeroMemory(@ddscaps, SizeOf(ddscaps));
17. ddscaps.dwCaps := DDSCAPS_BACKBUFFER;
18. hRet := FDDSPrimary.GetAttachedSurface(ddscaps, FDDSBack);
19. if Failed (hRet) then ErrorOut(hRet, 'GetAttachedSurface');
20. FDDSBack._AddRef;
21. FDDSImage1 := DDLoadBitmap(FDD, 'Star1.bmp', 0, 0);
22. if FDDSImage1 = nil then ErrorOut(DD_FALSE, 'DDLoadBitmap');
23. FDDSImage2 := DDLoadBitmap(FDD, 'Star2.bmp', 0, 0);
24. if FDDSImage2 = nil then ErrorOut(DD_FALSE, 'DDLoadBitmap');
25. FDDSImage3 := DDLoadBitmap(FDD, 'Star3.bmp', 0, 0);
26. if FDDSImage3 = nil then ErrorOut(DD_FALSE, 'DDLoadBitmap');
27. wrkBitmap := TBitMap.Create;
28. wrkBitmap.LoadFromFile ('Fighter.bmp');
...
Пояснение к программе
Данный фрагмент кода представляет собой важнейшую часть программы. В самом начале мы инициализируем объект DirectX, причем в разделе объявления глобальных переменных данный объект привязывается к седьмой версии, то есть эта программа после компиляции не станет работать на тех компьютерах, на которых не установлена хотя бы седьмая версия этого продукта. ...
private
{ Private declarations }
FDD : IDirectDraw7;
...
end;
...
Строки 1-5. Инициализируем объект FDD, который будет работать в экранном режиме 640 на 480 (не рекомендую изменять этот режим), а также с 16-битной цветовой палитрой. Строка 6. Эта строка нужна для определения ошибки при работе с экраном. Такая ошибка может произойти, если пользователь работает, например, с древним допотопным монитором или если установлена слишком низкая разрешающая способность. Строки 7-12. Каждый, даже мало знакомый с хитростями работы компьютера, знает, что для работы особенно мощных игр нужно большое количество оперативной памяти. Данные операторы резервируют оперативную память для работы программы. Строки 14-19. Эти операторы подготавливают память для загрузки в неё текстуры, при этом мы определяем тип текстуры. Я не стану подробно объяснять, что к чему, так как это может быть весьма малопонятным для многих начинающих программистов. Замечу лишь то, что каждый определенный объект в DirectX имеет свой строго определенный тип. Переменные для загрузки текстуры и изображении самолета и звезд мы загружаем в переменные предварительно объявленные в разделе private. ...
private
{ Private declarations }
FDD : IDirectDraw7;
FDDSBack : IDirectDrawSurface7;
FDDSImage1 : IDirectDrawSurface7;
FDDSImage2 : IDirectDrawSurface7;
FDDSImage3 : IDirectDrawSurface7;
FDDSFighter : IDirectDrawSurface7;
FDDSPrimary : IDirectDrawSurface7;
...
Строки 20-28. После того, как все предварительные операции проделаны, мы загружаем текстуры самолета и звезд из файлов типа BMP. Думаю, многие опытные программисты смогут работать с файлами других графических форматов.
Звездный фон
Так же как и самолет звезды загружаются из графических файлов, причем, для придания большей объемности мы загружаем три типа звезд, различающих по яркости. Координаты звезд — случайные числа. ...
Randomize;
for i := 0 to 6 - 1 do begin
Stars1 [i].X := random (640);
Stars1 [i].Y := random (480);
Stars2 [i].X := random (640);
Stars2 [i].Y := random (480);
Stars3 [i].X := random (640);
Stars3 [i].Y := random (480);
end;
...
Как вы уже поняли, звезды заполняются по всей области экрана. Теперь разберем еще один важный момент — поворот самолета. 1. if (Key = VK_ESCAPE) or (Key = VK_F12) then begin
2. Close;
3. Exit;
4. end else
5. if Key = VK_LEFT then StepX := StepX + 1 else
6. if Key = VK_RIGHT then StepX := StepX - 1 else
7. if Key = VK_UP then StepY := StepY + 1 else
8. if Key = VK_DOWN then StepY := StepY - 1;
9. if StepY < 1 then StepY := 1 else
10. if StepY > 3 then StepY := 3;
11. if StepX < -4 then StepX := -4 else
12. if StepX > 4 then StepX := 4;
13. with RotateBmp (wrkBitmap, 170, 135, arctan (StepX / StepY)) do begin
14. DDCopyBitmap (FDDSFighter, Handle, 0, 0, Width, Height);
15. Free
16. end;
Данный фрагмент кода представляет собой событие от клавиатуры. Он весьма прост. Когда вы нажимаете на клавишу Esc или F12, программа прекращает работать. Далее, при нажатии на клавишу вправо/влево вы изменяете угол наклона, но не больше установленной границы. Само же вращение происходит с помощью процедуры RotateBmp, важнейшим ее аргументом является угол поворота, который мы выразили с помощью обратно тригонометрической функции арктангенса. Как видите, без математики тут не обойтись. Но одной функции RotateBmp не достаточно, после того как мы повернули самолет, мы копируем полученное повернутое изображение, которое будет потом отображено, в противном случае, при нажатии на клавишу поворота, изображение моргнуло бы один и вернулось в исходное положение.
На этом пока все. В данной статье вы познакомились лишь с одним базовым, но очень важным компонентом библиотеки DirectX.
Александр Ковяков Софтерра
|
|