Изучаем DelphiX (Часть 5)
Материал из DRKB
Изучаем DelphiX. Часть 5: AI.[править | править код]
"Все люди - всего на всего сложный AI"
Здравствуйте! Сегодня я реализую у вас на глазах, простенький Ai который будет стрелять по вам, и двигаться к вам. Бороться с ним будет "очень просто" (клавиатуру не поломайте), не смотря на его простенькое строение. В виде шаблона я возьму пример из части 4.
Начнём делать всё постепенно, нам ведь некуда тропится, правильно?
Для начала в Uses добавим модуль math. В этом модуле находятся процедуры с математикой.
Далее добавляем перед implementation в var:
var
plres: Boolean; // plres - респаун: True - погиб 1 игрок, False - 2 игрок
fa: Boolean; // Выстрел нашего Ai True - стрелял, False - нет
Player: TPlayerOne;
PlayerAi: TPlayerTwo;
Процедура Domove изменяется у нашего Ai:
procedure TPlayerTwo.DoMove(MoveCount: Integer);
begin
inherited DoMove(MoveCount);
ang2 := Angle;
if y >= Form1.DXDraw1.SurfaceHeight - Image.Height then
y := Form1.DXDraw1.SurfaceHeight - Image.Height;
if x >= Form1.DXDraw1.SurfaceWidth - Image.Width then
x := Form1.DXDraw1.SurfaceWidth - Image.Width;
if y <= 0 then
y := 1;
if x <= 0 then
x := 1;
begin
if fa then
begin
if LngPolet - OldLngPolet >= 250 then
begin
Inc(LngPolet);
with TPlayerFa.Create(Engine) do
begin
Image := Form1.DXImageList1.Items.Find('pul');
X := Self.X + cos256(ang2) * 55;
Y := Self.y + sin256(ang2) * 55;
AngleFa := ang2;
OldLngPolet := LngPolet;
end;
fa := False;
end;
end;
LngPolet := LngPolet + MoveCount;
end;
Collision;
end;
Теперь идём в FormCreate и удаляем там всё кроме
procedure TForm1.FormCreate(Sender: TObject);
begin
Randomize;
end;
Кликаем на DxDraw и в свойствах ищем: "OnInitialize" создаём событие, и вставляем:
PlayerAi := TPlayerTwo.Create(DXSpriteEngine1.Engine);
PlayerAi.Image := DXImageList1.Items.Find('krut');
PlayerAi.X := 50;
PlayerAi.Y := 250;
PlayerAi.Width := PlayerAi.Image.Width;
PlayerAi.Height := PlayerAi.Image.Height;
Player := TPlayerOne.Create(DXSpriteEngine1.Engine);
Player.Image := Form1.dxImageList1.Items.Find('krut');
Player.x := 350;
Player.y := 250;
Player.Width := Player.Image.Width;
Player.Height := Player.Image.Height;
Теперь кидаем на форму простой таймер (я назвал его Ai). Параметры такие:
Enabled = true Interval = 1 Name = Ai
Создаём событие OnTime и пишем следующее:
PlayerAi.Angle := Trunc(1 / sin256(Trunc((Player.y-PlayerAi.y) / (Player.x-PlayerAi.x))));
if (Player.y-PlayerAi.y < 0) and (Player.x-PlayerAi.x > 0) then
PlayerAi.Angle := PlayerAi.Angle + 192;
If (Player.y-PlayerAi.y < 0) and (Player.x-PlayerAi.x < 0) then
PlayerAi.Angle := PlayerAi.Angle + 128;
If (Player.y-PlayerAi.y > 0) and (Player.x-PlayerAi.x < 0) then
PlayerAi.Angle := PlayerAi.Angle + 64;
if Player.x <= PlayerAi.x then
PlayerAi.x := PlayerAi.x - 2.5;
if Player.x > PlayerAi.x then
PlayerAi.x := PlayerAi.x + 2.5;
if Player.y <= PlayerAi.y then
PlayerAi.y := PlayerAi.y - 2.5;
if Player.y > PlayerAi.y then
PlayerAi.y := PlayerAi.y + 2.5;
if PlayerAi.x >= Player.x-140 then
begin
PlayerAi.x := PlayerAi.x - 2.5;
end;
if PlayerAi.y >= Player.y-140 then
begin
PlayerAi.y := PlayerAi.y - 2.5;
end;
if PlayerAi.y >= Player.y-150 then
begin
if PlayerAi.x >= Player.x-150 then
begin
fa := True;
end;
end;
Вот и всё, мы реализовали примитивный, и простенький Ai, ни капли не реалистичный, зато очень точный. Есть маленький совет: атакуйте издалека.
Ну а теперь Д/З:
- Осуществите более реалистичный разворот к игроку
- Реализуйте ошибки Ai (т.е. неточное попадание и т.д.)
- Чтобы AI не стрелял постоянно в одну и туже точку после гибели игрока
- И вообще, придумайте что-то своё
На это Д/З я не буду писать решение в следующей части. Реализуйте это, и отправьте мне на e-mail, и если всё будет хорошо, ты получишь предложение, от которого нельзя отказаться. Жду!!
Всё, что мы на кодили, здесь: part5.rar.
Author: Влад Энгельгардт
Source: https://gamedev.ru
ID: 03933