Ошибка времени выполнения: System.ArgumentException: Недопустимый параметр
Хотел сделать игру на подобие Zombie Smasher для курсовой работы, но в процессе игры она вылетает с ошибкой на строке 77 или вообще просто вылетает без ошибки. Не могу понять в чем проблема. Вот код:
uses GraphABC, ABCObjects, ABCButtons, System.Windows.Forms;
const
Width: integer = 512;
Height: integer = 512;
BG: string = 'bg.png';
ZombieImage: string = 'zombie.png';
BloodImage: string = 'blood.png';
MAX_CNT_ZOMBIES: integer = 9;
procedure EventTick(); forward;
procedure SetWindowConfigurations(); forward;
procedure MouseDown(x,y,mb:integer); forward;
procedure KeyPressed(key: integer); forward;
procedure UpdateScore(); forward;
procedure InitZombie(); forward;
procedure DestroyMenu(); forward;
procedure InitLabels(); forward;
procedure GameOver(); forward;
procedure StartGame(); forward;
procedure Rules(); forward;
procedure Menu(); forward;
var score, lives: integer;
scoreLabel, livesLabel: TextABC;
TimeOffset: System.TimeSpan;
GameStartTime: DateTime;
btn1, btn2, btn3: ButtonABC;
title: TextABC;
I: integer;
type
Zombie = class(Object)
public
zspeed: integer;
zpic: PictureABC;
alive: boolean;
constructor Create();
begin
zspeed := Random(4, 10);
zpic := PictureABC.Create(Random(80, 390), Random(5, 30), ZombieImage);
alive := true;
zpic.ToFront;
end;
destructor Destroy();
begin
if zpic = nil then exit;
zpic.Destroy();
zpic := nil;
end;
procedure Restart;
begin
zpic.MoveTo(Random(80, 390), Random(5, 30));
zpic.RedrawNow;
end;
procedure kill;
begin
zpic.ChangePicture(BloodImage);
zpic.ToBack;
zspeed := 0;
alive := false;
score += Random(10, 20);
end;
function Clicked(x,y: integer): boolean;
begin
Clicked := false;
if alive = false then exit;
if ((zpic.Position.X <= x) and ((zpic.Center.X*2 - zpic.Position.X) >= x)) and
((zpic.Position.Y <= y) and ((zpic.Center.Y*2 - zpic.Position.Y) >= y)) then
Clicked := true;
exit;
end;
procedure Move;
begin
if (zpic = nil) or (alive = false) then exit;
if zspeed is integer then
zpic.MoveOn(0, 1+zspeed)
else
zpic.MoveOn(0, 1);
end;
end;
var zombies: array [1..MAX_CNT_ZOMBIES] of Zombie;
procedure EventTick();
begin
if (DateTime.Now - GameStartTime) <> TimeOffset then
begin
TimeOffset := DateTime.Now - GameStartTime;
if (Trunc(TimeOffset.TotalMilliseconds) mod 2) = 0 then
begin
if zombies[i] <> nil then
begin
if zombies[i].Alive = false then
begin
zombies[I].Destroy();
zombies[I] := nil;
end
else if zombies[i].zpic.Position.Y >= Height then
begin
zombies[i].Restart();
Dec(lives);
end
else if zombies[i].Alive then
zombies[i].Move()
end;
UpdateScore();
if I = MAX_CNT_ZOMBIES then I := 1
else Inc(I);
end;
end;
if (zombies[i] = nil) and ((Trunc(TimeOffset.TotalMilliseconds) mod 99) = 0) then
zombies[I] := Zombie.Create();
end;
procedure SetWindowConfigurations();
begin
Window.Title := 'Zombie Smash';
Window.IsFixedSize := true;
Window.Width := Width;
Window.Height := Height;
Window.Fill(BG);
end;
procedure MouseDown(x,y,mb:integer);//нажали кнопку мыши
begin
for var i := 1 to MAX_CNT_ZOMBIES do
if zombies[i] <> nil then
if zombies[i].Clicked(x,y) then
begin
zombies[i].kill();
end;
end;
procedure KeyPressed(key: integer);
begin
case key of
VK_Escape:
Window.Close;
else;
end;
end;
procedure UpdateScore();
begin
scoreLabel.Text := $'Score: {score}';
livesLabel.Text := $'Lives: {lives}';
end;
procedure InitZombie();
begin
zombies[1] := Zombie.Create();
end;
procedure DestroyMenu();
begin
title.Destroy;
btn1.Destroy;
btn2.Destroy;
btn3.Destroy;
end;
procedure InitLabels();
begin
score := 0;
lives := 3;
scoreLabel := TextABC.Create(10, 10, 20, $'Score: {score}', clCoral);
livesLabel := TextABC.Create(10, 30, 20, $'Lives: {lives}', clCoral);
end;
procedure GameOver();
begin
LockDrawingObjects;
livesLabel.Text := 'GAME OVER';
livesLabel.FontSize := 40;
livesLabel.MoveTo(100, 180);
livesLabel.Color := clRed;
livesLabel.ToFront;
livesLabel.FontStyle := FontStyleType.fsBold;
scoreLabel.Text := $'Total Score: {score}';
scoreLabel.FontSize := 30;
scoreLabel.MoveTo(110, 240);
scoreLabel.Color := clGreen;
scoreLabel.ToFront;
livesLabel.FontStyle := FontStyleType.fsBold;
RedrawObjects();
end;
procedure StartGame();
begin
DestroyMenu();
InitZombie();
InitLabels();
GameStartTime := DateTime.Now;
i := 1;
//UnLockDrawingObjects();
while lives > 0 do
begin
EventTick();
end;
// Игра окончена
GameOver();
end;
procedure Rules();
begin
var msg := $'Все что тебе предстоит делать это нажимать на бегущих сверху вниз зомби.{chr(10)}И за это зарабатывать очки.{chr(10)}Игра будет продолжаться пока ты не проиграешь.';
MessageBox.Show(msg,'Правила', MessageBoxButtons.OK);
end;
procedure Menu();
begin
UnLockDrawingObjects;//LockDrawingObjects;
title := TextABC.Create(Width div 2 - 130, 70, 40, $' ZOMBIE{Chr(10)}SMASHER', GColor.Red);
btn1 := ButtonABC.Create(Width div 2 - 50, Height div 2, 100, 30, 'Играть', GColor.Gainsboro);
btn2 := ButtonABC.Create(Width div 2 - 50, Height div 2 + 60, 100, 30, 'Правила', GColor.Gainsboro);
btn3 := ButtonABC.Create(Width div 2 - 50, Height div 2 + 120, 100, 30, 'Выйти', GColor.Gainsboro);
//RedrawObjects;
btn1.OnClick := ()->System.Threading.Thread.Create(StartGame).Start();
btn2.OnClick := Rules;
btn3.OnClick := Window.Close;
end;
begin
SetWindowConfigurations();
OnMouseDown := MouseDown;
OnKeyDown := KeyPressed;
Menu();
end.
Игра жутко лагает, вылетает когда захочет, и иногда даже не запускается с первого раза.