Сегодня мы напишем с вами маленькую игрушку на подобие
танчиков. Я использую Делфи 7. Итак запускаем Делфи, в итоге у нас
автоматически создается форма и проект. Мы нажимает Файл—Сохранить и выбираем
папку, в которой будет находиться наша игра. Наш проект сохранен, теперь
создаем папку для хранения графики. И рисуем в графическом редакторе, например
пеинте, два вида танков и пулю. Танки должны быть нарисованы с поворотами в
разные стороны, на каждую сторону по две картинки с разным движением гусениц
(для имитации езды). Размер изображений я выбрал 60х60. Я рисовал одну
картинку, а потом просто поворачивал ее (Рисунок—Повернуть/Наклонить—повернуть
на 90 градусов). В итоге мы получаем что-то такое:
Под каждым рисунком вам видна его подпись. Буква в подписи означает
имя танка (одна буква для простоты), первая цифра обозначает номер поворота
(1-вверх, 2-вправо, 3-вниз, 4-влево), вторая цифра – номер движения гусеницы.
Далее кликаем на форме. В обджект инспекторе выбираем
вкладку EVENTS (это
события формы). Дважды кликам по
событию FormCreate
(создание формы). Откроется листинг в котором мы напишем загрузку всех
необходимых картинок для игры. И они будут загружаться сразу после появления
формы на экране.
Сначала обьявляем переменные.
После слова Var
перед Implementation,
которое немного выше места с курсором пишем следующее:
Tanki:array[1..2,1..2,1..4]of
TBitmap;
Textures:array[1..3] of TBitmap;
Flag:array[1..2]of TFlag;
Map:array[0..10,0..10] of integer;
Tank:array[1..4]of TTank;
Puli:array[1..20] of Tpulya;
Pulya,Buf:Tbitmap;
path:string;
qUp,qDown,qLeft,qRight:boolean;
i,j:integer;
Теперь обьясняю. Массив Tanki будет хранить
картинки (Битмапы (БМП)) всех танков. В нашем случае «1..2» означает два вида
танков, следующие «1..2» означают два вида движения гусеницы, «1..4» означает
поворот танка в 4 стороны. Переменная Pulya будет хранить
картинку выпущенных пуль. Path будет хранить путь к
нашей игре на компьютере, независимо где находиться папка при запуске. Она
нужна для правильной загрузки картинок, можно обойтись без нее, но если
загружать много картинок из разных папок и тд., могут произойти ошибки, которые
будут только иногда появляться. Чтобы этого не произошло мы используем эту
переменную. Buf – это графический буфер, в
который мы будем все прорисовывать, а потом этот буфер рисовать на саму форму.
Если рисовать без него, то когда будут рисоваться одни картинки поверх других,
вся игра будет мигать. Up,Down,Left,Right
– это клавиши управления танком, с их помощью мы будем проверять какая из них
нажата последней и куда нам ехать.
Далее пишем саму загрузку картинок с паки img, которая находится в папке с игрой. i,j – это просто вспомогвтельные
переменные. Flag – это характеристики и картинки
флагов соперников на карте. Textures – массив картинок обьектов для заполнения игровой
карты. Map – это массив клеток игровой карты, в котором храняться
номера текстур для каждой ячейки.
procedure
TForm1.FormCreate(Sender: TObject);
var
i,j:integer;
begin
path:=extractFileDir(Application.ExeName);
//zagruzka kartinok tankov
for
i:=1 to 4 do
for
j:=1 to 2 do
begin
Tanki[1,i,j]:=Tbitmap.create;
Tanki[2,i,j].TransparentColor:=clWhite;
Tanki[1,i,j].loadfromFile(path+'\img\'+'t'+inttostr(i)+inttostr(j)+'.bmp');
Tanki[2,i,j]:=Tbitmap.create;
Tanki[2,i,j].TransparentColor:=clWhite;
Tanki[2,i,j].loadfromFile(path+'\img\'+'q'+inttostr(i)+inttostr(j)+'.bmp');
end;
//zagruzka tekstur
for
i:=1 to 4 do
begin
Textures[i]:=Tbitmap.Create;
Textures[i].LoadFromFile(path+'\img\'+inttostr(i)+'.bmp');
end;
//zagruzka puli
Pulya:=Tbitmap.Create;
Pulya.LoadFromFile(path+'\img\p.bmp');
Buf:=Tbitmap.Create;
Buf.Width:=600;
buf.Height:=600;
qLeft:=false;
qRight:=false;
qUp:=false;
qDown:=false;
end;
Как видно,
сначала мы создаем место под картинки, а затем загружаем картинку из
папки. Мы установили ширину и высоту буфера 600х600. Затем я устанавливаю
клавиши управления танком в неактивное положение (w-a-s-d). Следующим шагом будет
создание записи для характеристик нашего танка. После слова Type в самом
верху пишем:
TTank=record
Speed,x,y,Povorot:integer;
Go,Anim,Fight,Vistrelil:boolean;
Zaderhka_Vistrela,Max_vistrel:integer;
end;
Speed – это скорость танка
X – координата х на карте игры
Y – координата у на карте игры
Povorot – номер поворота танка
Anim – Номер анимации гусеницы (два значения истина- первая анимация, лож
– вторая анимация)
Go – может
принимать два значения истина (true)
и лож (false). Переменная показывает движется танк или стоит на одном месте.
Fight – выстрел танка
Zaderhka_Vistrela – нужна для отсчета времени между
выстрелами
Max_vistrel – задержка выстрела.
Vistrelil – показатель
выстрелил уже танк или нет.
Вторую запись
пишем для всех выпущенных пуль:
Tpulya=record
x,y,speed,povorot:integer;
visible:boolean;
end;
x,y – координаты
speed – скорость
povorot – в какую сторону лететь
visible – видимость (видима пуля
только когда выпущена танком)
После слова Var написаны следующие строки
Tank:array[1..4]of
TTank;
Puli:array[1..20]
of Tpulya;
Это значит, что четыре танка будут иметь эти характеристики
и 20 пуль будут иметь свои характеристики.
Теперь напишем начальные характеристики нашего танка и всех
пуль. А затем случайное создание карты. После загрузки картинки пули пишем
строки:
Tank[1].Speed:=5;
Tank[1].x:=60;
Tank[1].y:=60;
Tank[1].Povorot:=1;
Tank[1].Go:=false;
Tank[1].Anim:=1;
Tank[1].Fight:=false;
Tank[1].Zaderhka_Vistrela:=0;
Tank[1].Max_vistrel:=10;
Tank[1].Vistrelil:=false;
for i:=1 to 20 do
begin
Puli[i].x:=0;
Puli[i].y:=0;
Puli[i].speed:=10;
Puli[i].povorot:=0;
Puli[i].visible:=false;
end;
Далее пишем случайное генерирование карты 10х10 клеточек:
//generirovaniye
karti
randomize;
for i:=0 to 9 do
for j:=0 to 9 do
begin
map[i,j]:=random(100)+1;
if map[i,j]<=50 then map[i,j]:=1;
if (map[i,j]>50) and (map[i,j]<=80)
then map[i,j]:=2;
if (map[i,j]>80) and (map[i,j]<=100)
then map[i,j]:=3;
end;
map[9,0]:=4;
map[trunc(Tank[1].x/60),trunc(Tank[1].y/60)]:=1;
Теперь при появлении танка под ним будет только проходимый
участок.
Далее кликаем по форме и перетаскиваем с вкладки System компонент
Timer, который не будет
виден при запуске игры, но каждый промежуток времени он будет прорисовывать все
изменения игры. Дважды кликаем по таймеру и пишем прорисовку карты и прорисовку
нашего танка поверх карты:
//prorisovka
karti
for i:=0 to 9 do
for j:=0 to 9 do
buf.Canvas.Draw(i*60,j*60,Textures[ map[i,j]
]);
if
Tank[1].Go=true then
begin
if Tank[1].Anim=1 then Tank[1].Anim:=2
else Tank[1].Anim:=1;
end;
buf.Canvas.Draw(Tank[1].x,Tank[1].y,Tanki[1,Tank[1].povorot,Tank[1].anim]);
form1.Canvas.Draw(0,0,buf);
Сохраните проект и запустите его клавишей F9. Вы видите на экране наш
недвижимый танк в указаних начальних координатах. Анимация гусениц вступит в
силу после того, как мы сделаем обработку нажатих управляючих клавиш. Кликаем
по нашей форме, а затем дважды щелкаем по событию OnKeyDown. Это событие проверяет нажатые
клавиши. Пишем там следующий код:
if key=87 then
begin
qUp:=true;
Tank[1].Go:=true;
Tank[1].Povorot:=1;
end;
if key=65 then
begin
qLeft:=true;
Tank[1].Go:=true;
Tank[1].Povorot:=4;
end;
if key=83 then
begin
qDown:=true;
Tank[1].Go:=true;
Tank[1].Povorot:=3;
end;
if key=68 then
begin
qRight:=true;
Tank[1].Go:=true;
Tank[1].Povorot:=2;
end;
Из этого видно, что если нажата клавиша с номерами 87 (w), 65 (a), 83 (s), 68 (d), то танку присваиваем движение гусениц и делаем клавишу нажатой. Плюс к
тому же мы определяем поворот танка. Затем дважды кликаем по событию OnKeyUp. Здесь мы проверяем если не нажата ни одна из
управляючих кнопок, то анимация танка отключается. И отключаем не нажате
клавиши.
if (key=87) then qUp:=false;
if (key=65) then qLeft:=false;
if (key=83) then qDown:=false;
if (key=68) then qRight:=false;
if (qUp=false) and (qLeft=false) and
(qDown=false) and (qRight=false) then Tank[1].Go:=false;
Чтобы анимация была быстрее кликните по таймеру и выставте
интервал 100. Сохраните и запустите проект. Теперь наш танк умеет поворачивать
и ездить. Теперь наша задача сделать, чтобы он не мог проезжать через
непроходимые участки. Нужно изменить написанный ранее код изменения координат.
//izmeneniye
koordinat tanka
if Tank[1].Go=true
then
begin
//vverh
if (Tank[1].Povorot=1) and
(map[trunc(Tank[1].x/60),trunc( (Tank[1].y-Tank[1].Speed)/60)]=1)
and (map[trunc( (Tank[1].x+59) /60),trunc(
(Tank[1].y-Tank[1].Speed)/60)]=1)
and (Tank[1].y-Tank[1].Speed>=0) then
Tank[1].y:=Tank[1].y-Tank[1].Speed;
//vniz
if (Tank[1].Povorot=3) and
(map[trunc(Tank[1].x/60),trunc( (Tank[1].y+Tank[1].Speed+59)/60)]=1)
and (map[trunc( (Tank[1].x+59) /60),trunc(
(Tank[1].y+Tank[1].Speed+59)/60)]=1)
and (Tank[1].y+Tank[1].Speed<=540) then
Tank[1].y:=Tank[1].y+Tank[1].Speed;
//vpravo
if (Tank[1].Povorot=2) and (map[trunc(
(Tank[1].x+Tank[1].Speed+59)/60),trunc(Tank[1].y/60)]=1)
and (map[trunc(
(Tank[1].x+Tank[1].Speed+59)/60),trunc( (Tank[1].y+59) /60)]=1)
and (Tank[1].x+Tank[1].Speed<=540) then
Tank[1].x:=Tank[1].x+Tank[1].Speed;
//vlevo
if (Tank[1].Povorot=4) and (map[trunc(
(Tank[1].x-Tank[1].Speed)/60),trunc(Tank[1].y/60)]=1)
and (map[trunc(
(Tank[1].x-Tank[1].Speed)/60),trunc( (Tank[1].y+59) /60)]=1)
and (Tank[1].x-Tank[1].Speed>=0) then
Tank[1].x:=Tank[1].x-Tank[1].Speed;
end;
Таким образом когда танк будет ехать будет проверяться
попадание двух его передних угров на попадание в непроходимый участок. К тому
же мы не позволяем выехать танку за пределы игровой карты.
Теперь нужно научить наш танк стрелять. Для этого мы в
управление танком добавим клавишу пробел (например), для стрельбы. А затем
будем создавать пулю и просчитывать в какую сторону ей лететь и когда
пропадать.
Для пуль создается тип с номерами пуль, координатами и поворотом. Но это будет в продолжении статьи
Автор: Соколов Виталий Источник: delgame.at.ua
|