239 lines
5.6 KiB
ObjectPascal
239 lines
5.6 KiB
ObjectPascal
uses ABCObjects,GraphABC,Timers;
|
|
|
|
const
|
|
clPlayer = Color.BurlyWood;
|
|
|
|
var
|
|
kLeftKey,kRightKey: boolean;
|
|
kSpaceKey: integer;
|
|
/// Игрок
|
|
Player: RectangleABC;
|
|
/// Таймер движения врагов
|
|
t: Timer;
|
|
/// Флаг конца игры
|
|
EndOfGame: boolean;
|
|
/// Количество неигровых объектов
|
|
StaticObjectsCount: integer;
|
|
/// Счетчик выигрышей
|
|
Wins: integer;
|
|
/// Счетчик проигрышей
|
|
Falls: integer;
|
|
/// Информационная строка
|
|
InfoString: RectangleABC;
|
|
/// Сообщение в начале игры
|
|
NewGame: RoundRectABC;
|
|
|
|
type
|
|
KeysType = (kLeft,kRight);
|
|
|
|
/// Класс пули
|
|
Pulya = class(CircleABC)
|
|
public
|
|
constructor Create(x,y: integer);
|
|
procedure Move; override;
|
|
end;
|
|
|
|
/// Класс врага
|
|
Enemy = class(RectangleABC)
|
|
public
|
|
constructor Create(x,y,w: integer);
|
|
procedure Move; override;
|
|
end;
|
|
|
|
constructor Pulya.Create(x,y: integer);
|
|
begin
|
|
inherited Create(x,y,5,clRed);
|
|
dx := 0;
|
|
dy := -5;
|
|
end;
|
|
|
|
procedure Pulya.Move;
|
|
begin
|
|
inherited Move;
|
|
if Top<0 then
|
|
Visible := False;
|
|
for var j:=StaticObjectsCount to Objects.Count-1 do
|
|
// При столкновении пуля и объект становятся невидимыми
|
|
if (Objects[j]<>Self) and Intersect(Objects[j]) then
|
|
begin
|
|
Objects[j].Visible := False;
|
|
Visible := False;
|
|
end;
|
|
end;
|
|
|
|
constructor Enemy.Create(x,y,w: integer);
|
|
begin
|
|
inherited Create(x,y,w,20,clRandom);
|
|
if Random(2)=0 then
|
|
dx := 5
|
|
else dx := -5;
|
|
dy := 0;
|
|
end;
|
|
|
|
procedure Enemy.Move;
|
|
begin
|
|
if Random(2)<>0 then
|
|
Exit;
|
|
if Random(10)=0 then
|
|
dy := 5;
|
|
if (Left<0) or (Left+Width>Window.Width) or (Random(30)=0) then
|
|
dx := -dx;
|
|
inherited Move;
|
|
if dy<>0 then
|
|
dy := 0;
|
|
if Top>Window.Height-50 then
|
|
EndOfGame := True;
|
|
end;
|
|
|
|
/// Количество врагов
|
|
function NumberOfEnemies: integer;
|
|
begin
|
|
Result := 0;
|
|
for var i:=0 to Objects.Count-1 do
|
|
if Objects[i] is Enemy then
|
|
Result += 1;
|
|
end;
|
|
|
|
/// Создание игрока и врагов
|
|
procedure CreateObjects;
|
|
begin
|
|
Player := new RectangleABC(280,WindowHeight-30,100,20,clPlayer);
|
|
for var i:=1 to 100 do
|
|
begin
|
|
var r1 := new Enemy(Random(WindowWidth-50),40+Random(10),50);
|
|
r1.TextVisible := True;
|
|
r1.Number := i;
|
|
end;
|
|
end;
|
|
|
|
/// Разрушение игрока и врагов
|
|
procedure DestroyObjects;
|
|
begin
|
|
for var i:=Objects.Count-1 downto StaticObjectsCount do
|
|
Objects[i].Destroy;
|
|
end;
|
|
|
|
/// Перемещение врагов
|
|
procedure MoveObjects;
|
|
begin
|
|
for var i:=StaticObjectsCount+1 to Objects.Count-1 do
|
|
Objects[i].Move;
|
|
end;
|
|
|
|
/// Удаление уничтоженных объектов
|
|
procedure DestroyKilledObjects;
|
|
begin
|
|
for var i:=ObjectsCount-1 downto StaticObjectsCount+1 do
|
|
if not Objects[i].Visible then
|
|
Objects[i].Destroy;
|
|
end;
|
|
|
|
/// Обработчик нажатия клавиши
|
|
procedure KeyDown(Key: integer);
|
|
begin
|
|
case Key of
|
|
vk_Left: kLeftKey := True;
|
|
vk_Right: kRightKey := True;
|
|
vk_Space: if kSpaceKey=2 then kSpaceKey := 1;
|
|
end;
|
|
end;
|
|
|
|
/// Обработчик отжатия клавиши
|
|
procedure KeyUp(Key: integer);
|
|
begin
|
|
case Key of
|
|
vk_Left: kLeftKey := False;
|
|
vk_Right: kRightKey := False;
|
|
vk_Space: kSpaceKey := 2;
|
|
end;
|
|
end;
|
|
|
|
/// Изменение информационной строки
|
|
procedure ChangeInfoString;
|
|
begin
|
|
InfoString.Text := 'Врагов: '+IntToStr(NumberOfEnemies)+' Побед: '+IntToStr(Wins)+' Поражений: '+IntToStr(Falls);
|
|
end;
|
|
|
|
/// Обработчик нажатия символьной клавиши
|
|
procedure KeyPress(Key: char);
|
|
begin
|
|
if (Key in ['G','П','g','п']) and EndOfGame then
|
|
begin
|
|
NewGame.Visible := False;
|
|
EndOfGame := False;
|
|
t.Start;
|
|
CreateObjects;
|
|
kSpaceKey := 2;
|
|
kLeftKey := False;
|
|
kRightKey := False;
|
|
end;
|
|
end;
|
|
|
|
/// Обработчик отжатия мыши
|
|
procedure MouseUp(x,y,mb: integer);
|
|
begin
|
|
if NewGame.PTInside(x,y) then
|
|
KeyPress('G');
|
|
end;
|
|
|
|
/// Обработчик таймера
|
|
procedure TimerProc;
|
|
begin
|
|
if kLeftKey and (Player.Left>0) then
|
|
Player.MoveOn(-10,0);
|
|
if kRightKey and (Player.Left+Player.Width<WindowWidth) then
|
|
Player.MoveOn(10,0);
|
|
if kSpaceKey=1 then
|
|
begin
|
|
new Pulya(Player.Left+Player.Width div 2,Player.Top-10);
|
|
kSpaceKey := 0;
|
|
end;
|
|
MoveObjects;
|
|
DestroyKilledObjects;
|
|
RedrawObjects;
|
|
ChangeInfoString;
|
|
var n := NumberOfEnemies;
|
|
// Страховка от случая, когда процедура таймера выполняется одновременно в нескольких потоках
|
|
if n=0 then
|
|
EndOfGame := True;
|
|
if EndOfGame then
|
|
begin
|
|
if t.Enabled=False then Exit;
|
|
t.Stop;
|
|
if n>0 then
|
|
Falls += 1
|
|
else Wins += 1;
|
|
NewGame.Visible := True;
|
|
DestroyObjects;
|
|
ChangeInfoString;
|
|
RedrawObjects;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Window.Title := 'Стрелялка';
|
|
Window.IsFixedSize := True;
|
|
ClearWindow(clBlack);
|
|
LockDrawingObjects;
|
|
EndOfGame := True;
|
|
InfoString := new RectangleABC(0,0,Window.Width,38,Color.DarkBlue);
|
|
InfoString.Bordered := False;
|
|
InfoString.FontColor := clWhite;
|
|
InfoString.TextScale := 0.9;
|
|
|
|
var zz := 100;
|
|
NewGame := new RoundRectABC(zz,200,400,200,30,Color.Violet);
|
|
NewGame.Center := Window.Center;
|
|
NewGame.Text := 'G - Новая игра';
|
|
StaticObjectsCount := Objects.Count;
|
|
ChangeInfoString;
|
|
RedrawObjects;
|
|
|
|
OnKeyDown := KeyDown;
|
|
OnKeyPress := KeyPress;
|
|
OnKeyUp := KeyUp;
|
|
OnMouseUp := MouseUp;
|
|
|
|
t := new Timer(1,TimerProc);
|
|
end.
|