Как написать игру на паскале abc

К оглавлению | Назад | Вперёд

Все программы, код которых выложен здесь, являются работоспособными. Ниже приведены возможные варианты реализации игр «Крестики-нолики» и «Змейка» на PascalABC.Net 3.0.

Крестики-нолики[править]

Описание алгоритма
  1. Отрисовать игровое поле.
  2. Позволить сделать шаг игроку.
  3. Проверить выиграл ли кто-то.
  4. Если да — выиграл текущий игрок, иначе — вернуться к шагу 1.

Управление:

  • Левая кнопка мыши — установить крестик/нолик.
uses GraphABC;
const
  N = 2;
  Z = '0';
  K = 'X';
  Size = 200;
  Border = 1;
  Sx = 1200;
  Sy = 70;

var
  Matrix: array [0..N, 0..N] of char;
  Player1: boolean;

procedure Draw();
  procedure DrawZ(i, j: integer);
  begin
    SetPenColor(clCyan);
    SetPenWidth(4);
    var size2 := Size div 2;
    DrawCircle((i + 1) * Size - size2, (j + 1) * Size - size2, Round(size2 * 0.7));
  end;
  
  procedure DrawK(i, j: integer);
    procedure RLine(x, y, x1, y1: real):=Line(Round(x), Round(y), Round(x1), Round(y1));

  begin
    SetPenColor(clPink);
    SetPenWidth(4);
    var size2 := Size div 2 * 0.3;
    var cx1 := i * Size + size2;
    var cy1 := j * Size + size2;
    var cx2 := (i + 1) * Size - size2;
    var cy2 := (j + 1) * Size - size2;
    RLine(cx1, cy1, cx2, cy2);
    RLine(cx1, cy2, cx2, cy1);
  end;

  begin
    ClearWindow(clBlack);
    if Player1 then SetWindowCaption('Ходит первый игрок') else SetWindowCaption('Ходит второй игрок');
    for var i := 0 to N do
      for var j := 0 to N do
      begin
        SetPenColor(clLightBlue);
        SetPenWidth(1);
        DrawRectangle(i * Size + Border, j * Size + Border, (i + 1) * Size - Border, (j + 1) * Size - Border);
        if Matrix[i, j] = Z then DrawZ(i, j)
        else if Matrix[i, j] = K then DrawK(i, j);
      end;
    Redraw();
  end;

function Won(c: char): boolean;
var
  count: byte;
begin
  Result := false;
  for var i := 0 to N do
  begin
    count := 0;
    for var j := 0 to N do
      if Matrix[i, j] = c then Inc(count);
    if count = 3 then Result := true;
  end;
  
  if not Result then
  begin
    for var i := 0 to N do
    begin
      count := 0;
      for var j := 0 to N do
        if Matrix[j, i] = c then Inc(count);
      if count = 3 then Result := true;
    end;
    
    if not Result then
    begin
      count := 0;
      for var i := 0 to N do
        if Matrix[i, i] = c then Inc(count);
      if count = 3 then Result := true;
      
      if not Result then
      begin
        count := 0;
        for var i := 0 to N do
          if Matrix[N - i, i] = c then Inc(count);
        if count = 3 then Result := true;
      end;
    end;
  end;
end;

function IsFull(): boolean;
begin
  Result := true;
  for var i := 0 to N do
    for var j := 0 to N do
      if (Matrix[i, j] <> Z) and (Matrix[i, j] <> K) then
      begin
        Result := false;
        break;
      end;
end;

procedure MouseDown(x, y, mb: integer);
  procedure ShowWinner(s: string; c: Color);
  begin
    SetWindowCaption('Результат игры');
    Sleep(2000);
    SetWindowSize(Sx, Sy);
    CenterWindow();
    ClearWindow(clBlack);
    
    SetFontSize(16);
    SetFontStyle(fsBold);
    SetFontColor(c);
    DrawTextCentered(0, 0, Sx, Sy, s);
    
    Redraw();
    Sleep(2000);
    Halt();
  end;

begin
  var i := x div Size;
  var j := y div Size;
  if (Matrix[i, j] <> Z) and (Matrix[i, j] <> K) then
  begin
    if Player1 then Matrix[i, j] := Z else Matrix[i, j] := K;
    Draw();
    
    var winnerExists := Won(Z) or Won(K);
    if winnerExists then
      if Player1 then ShowWinner('Игрок первый победил!', clLightBlue) else ShowWinner('Игрок второй победил!', clLightBlue);
    
    if IsFull() and not winnerExists then ShowWinner('Ничья!', clOrange);
    
    Player1 := not Player1;
  end;
end;

begin
  var Size2 := Size * 3;
  SetWindowIsFixedSize(true);
  SetWindowSize(Size2, Size2);
  CenterWindow();
  LockDrawing();
  
  Player1 := true;
  Draw();
  
  OnMouseDown := MouseDown;
end.

Змейка[править]

==Упрощенный вариант== (просто змейка которой можно управлять)

Описание алгоритма
  1. Нарисовать змейку.
  2. Если нажали клавишу — добавить новую точку, в которую перешла голова змейки, в список и удалить первую точку в списке. Перейти к шагу 1.

Управление:

  • W — вверх.
  • S — вниз.
  • A — влево.
  • D — вправо.
uses GraphABC;
const
  Size = 20;

var
  Snake: List<Point>;

procedure Draw();
begin
  ClearWindow();
  Polyline(Snake.ToArray());
  
  var c := Snake.Count - 1;
  Circle(Snake[c].X, Snake[c].Y, 5);
  Redraw();
end;

procedure KeyDown(Key: integer);
begin
  var c := Snake.Count - 2;
  case Key of
    VK_Left:
      begin
        Snake.RemoveAt(0);
        Snake.Add(new Point(Snake[c].X - Size, Snake[c].Y));
      end;
    VK_Right:
      begin
        Snake.RemoveAt(0);
        Snake.Add(new Point(Snake[c].X + Size, Snake[c].Y));
      end;
    VK_Up:
      begin
        Snake.RemoveAt(0);
        Snake.Add(new Point(Snake[c].X, Snake[c].Y  - Size));
      end;
    VK_Down:
      begin
        Snake.RemoveAt(0);
        Snake.Add(new Point(Snake[c].X, Snake[c].Y  + Size));
      end;
  end;
  Draw();
end;

begin
  LockDrawing();
  SetSmoothingOff();
  
  Snake := new List<Point>();
  for var x := 1 to 30 do
    Snake.Add(new Point(x * Size, Size));
  
  Draw();
  OnKeyDown := KeyDown;
end.

Возрастающая последовательность[править]

uses GraphABC, ABCObjects;
const
  Border = 100;


var
  Obj: CircleABC;
  DX, DY: integer;
  Move: boolean;
  Numbers: TCircles;

function IsEqual(L2: TCircles): boolean;
begin
  Result := true;
  for var i := 0 to L2.Count - 1 do
    if Numbers[i].Number <> L2[i].Number then
    begin
      Result := false;
      break;
    end;
end;

procedure MouseUp(x, y, mb: integer);
procedure MouseMove(x, y, mb: integer);
begin
  if mb = 1 then
    if not Move then
    begin
      for var i := 0 to Numbers.Count - 1 do
        if Numbers[i].PtInside(x, y) then
        begin
          DX := x - Numbers[i].Position.X;
          DY := y - Numbers[i].Position.Y;
          Obj := Numbers[i];
          
          Move := true;
          break;
        end;
    end
    else
      Obj.Position := new Point(x - Dx, y - Dy);
end;

begin
  var W := Window.Width - 2 * Border;
  var H := Window.Height - 2 * Border;
  
  Numbers := new TCircles();
  for var i := 0 to 6 do
  end
    Numbers.Add(new CircleABC(Border + Random(W), Border + Random(H), 30, clRandom()));
    Numbers.Last().Number := i;
  
  Move := false;
  OnMouseMove := MouseMove;
  OnMouseUp := MouseUp;
end.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
uses crt,GraphABC;
const
speed=1;
var i,pic,pik,j,h,w,t,d: integer;  a:char;
begin
LockDrawing;
i:=200; d:=1;
while((i>50) and (i<800)) do
begin
i:=i+d;
setwindowsize(1280,1024);
ClearWindow;
line(0,300,1600,300);
FloodFill(0,200,clMoneyGreen);
FloodFill(400,500,clSilver);
line(i+380,200,i+410,200);
line(i+380,200,i+390,210);
line(i+400,210,i+410,200);
line(i+100,270,i+120,270);
line(i+300,270,i+320,270);
line(i+200,270,i+220,270);
SetBrushColor(clred);
Rectangle(i+20,230,i+100,280);
Rectangle(i+120,230,i+200,280);
Rectangle(i+220,230,i+300,280);
SetBrushColor(clyellow);
RoundRect(i+320,200,i+365,280,30,20);
SetBrushColor(clSkyBlue);
RoundRect(i+320,230,i+420,280,30,20);
Rectangle(i+390,230,i+400,210);
Rectangle(i+390,230,i+400,210);
Rectangle(i+390,230,i+400,210);
Rectangle(i+390,230,i+400,210);
SetBrushColor(clyellow);
circle(i+30,290,10);
circle(i+90,290,10);
circle(i+130,290,10);
circle(i+190,290,10);
circle(i+230,290,10);
circle(i+230,290,10);
circle(i+230,290,10);
circle(i+230,290,10);
circle(i+290,290,10);
circle(i+345,278,22);
circle(i+377,288,12);
circle(i+400,288,12);
if keypressed then
 begin a:=readkey;  d:=-d;
 if a=chr(32) then d:=d*2;
 end;
Redraw;
 
end;
end.

Учебник по программированию. Создание сайтов. Первые шаги.

§19. Клавиатурный тренажёр. Игра «Гонки».

Клавиатурный тренажёр.

Думаю, что каждому, кто дочитал эту книгу до этого места, не терпится написать настоящую программу. Предлагаю написать клавиатурный тренажёр, т.к. если вы собираетесь стать программистом, то вам просто необходимо научиться набирать текст, не глядя в клавиатуру. С помощью такой программы вы сможете этому тренироваться.

Вначале разберём, каким должен быть наш клавиатурный тренажёр, затем можно будет писать код программы.

Клавиатурный тренажёр должен предлагать нажать какую либо клавишу и ждать её нажатия. Если клавиша нажата верно, то он должен предложить нажать следующую, если не верно, то это должно считаться ошибкой, а тренажёр должен ждать нажатия верной клавиши. Количество ошибок должно считаться.

Вначале, в первом уровне, должны предлагаться для нажатия клавиши «J» и «F», т.к. в любой компьютерной клавиатуре на этих клавишах  есть небольшие бугорки. Эти бугорки являются ориентиром, относительно которых можно найти все другие клавиши. При наборе текста не глядя в клавиатуру, эти бугорки находятся на ощупь, затем на них устанавливаются указательные пальцы обеих рук. Соответственно эти клавиши «J» и «F» нажимаются указательными пальцами правой и левой рук.

Затем, во втором уровне, необходимо добавить ещё две клавиши, например «D» и «K», т.к. они находятся радом с предыдущими.

Далее, в третьем уровне, должны добавиться ещё две клавиши. В четвёртом  ещё две. И так далее, пока не начнут предлагаться все клавиши.

Клавиши должны каждый раз предлагаться в различных последовательностях.

Для того, что бы не подсматривать в клавиатуру, её необходимо нарисовать на экране, при этом предлагаемые клавиши можно подсвечивать каким либо цветом.

Так же  необходимо вывести палец, которым рекомендуется нажимать данную клавишу. Названия пальцев можно обозначить следующим образом:

Далее в таблице приведены клавиши и соответствующие им пальцы:

QЛ5

WЛ4

EЛ3

RЛ2

TЛ2

YП2

UП2

IП3

OП4

PП5

AЛ5

SЛ4

DЛ3

FЛ2

GЛ2

HП2

JП2

KП3

LП4

;П5

‘–П5

ZЛ5

XЛ4

CЛ3

VЛ2

BЛ1

NП2

MП2

,П3

.П4

Пробел П1

Внимательно изучите, какую клавишу, каким пальцем необходимо нажимать. Думаю, что логика такого расклада будет вам понятна.

Теперь перейдём непосредственно к программированию.

Клавиатуру можно нарисовать с помощью символов следующим образом:

— — — — — — — — — —

| Q | W | E | R | T | Y | U | I | O | P |

— — — — — — — — — —

  — — — — — — — — — — —

| A | S | D | F | G | H | J | K | L | ; | ‘ |

  — — — — — — — — — — —

   — — — — — — — — —

  | Z | X | C | V | B | N | M | , | . |

   — — — — — — — — —

Разную последовательность предлагаемых клавиш можно реализовать с помощью функции Random. Для этого можно создать массив клавиш, в котором первые две клавиши «J» и «F» будут иметь индексы 1 и 2, вторые две клавиши «D» и «K» 3 и 4, и т.д. Для получения случайной клавиши из первых двух, вызовем функцию Random(1,2). Для получения клавиши из четырёх Random(1,4). Так же в этом же массиве мы можем сохранить координаты X и Y этих клавиш на экранной клавиатуре для того, что бы подсвечивать их, а так же палец, которым нужно их нажимать. Реализовать это можно с помощью типа запись. Т.е. у нас получится массив данных типа запись.

У меня получился следующий код такого клавиатурного тренажёра:

Unit MKlavTren;

uses CRT;

type symbols = record//Тип для хранения клавиш в массиве

       number:byte;//Порядковый номер символа клавиши

            x:byte;//Координата Х на экранной клавиатуре

            y:byte;//Координата У на экранной клавиатуре

            p:string[2]//Палец, которым нужно нажимать клавишу

            end;

Var LatMassiv: array [1..30] of symbols;//Массив для хранения клавиш

    Oshibki:integer;//Счётчик ошибок

//Процедура выводит экранную клавиатуру

Procedure WriteLatKlav;

begin

  gotoxy(18,16);

  writeln(‘ — — — — — — — — — — ‘);

  gotoxy(18,17);

  writeln(‘| Q | W | E | R | T | Y | U | I | O | P |’);

  gotoxy(18,18);

  writeln(‘ — — — — — — — — — — ‘);

  gotoxy(19,19);

  writeln(‘ — — — — — — — — — — — ‘);

  gotoxy(19,20);

  writeln(‘| A | S | D | F | G | H | J | K | L | ; | » |’);

  gotoxy(19,21);

  writeln(‘ — — — — — — — — — — — ‘);

  gotoxy(20,22);

  writeln(‘ — — — — — — — — — ‘);

  gotoxy(20,23);

  writeln(‘| Z | X | C | V | B | N | M | , | . |’);

  gotoxy(20,24);

  writeln(‘ — — — — — — — — — ‘);

end;

//Процедура заполняет массив латинских клавиш

Procedure ZapolnenieLatMassiv;

begin

//Для примера заполнено только 4 клавиши

  with LatMassiv[1] do begin number:=106; x:=45; y:=20; p:=‘П2’; end;//j

  with LatMassiv[2] do begin number:=102; x:=33; y:=20; p:=‘Л1’; end;//f

  with LatMassiv[3] do begin number:=107; x:=49; y:=20; p:=‘П3’; end;//k

  with LatMassiv[4] do begin number:=100; x:=29; y:=20; p:=‘Л3’; end;//d

end;

//Непосредственно сам уровень тренировки набора латинских клавиш

//Параметр slojnost — количество клавиш

Procedure LatLevel(slojnost:byte);

var f:boolean;//Если клавиши правильная, то false и выходим из цикла

    c:char;//Для хранения нажатой клавиши

    n:byte;//Индекс клавиши в массиве

begin

//Каждый уровень предлагет 10 клавиш для нажатия

for var i:=1 to 10 do

  begin

//Выводим предлагаемую клавишу и рекомендуемый палец

    gotoxy(40,9);

    n:=random(1,slojnost);

    write(chr(LatMassiv[n].number));

    GotoXY(39,14);

    write(LatMassiv[n].p);

//Подсвечиваем клавишу на экранной клавиатуре   

    gotoxy(LatMassiv[n].x-1,latmassiv[n].y);

    TextBackground(red);

    Textcolor(15);

    write(‘ ‘,chr(LatMassiv[n].number-32),‘ ‘);

    Textcolor(black);

    TextBackground(7);

//Входим в цикл считывания нажатой клавиши

    f:=true;

    while f do

      begin

        if keypressed then

          begin

            c:=readkey;

            if ord(c)=LatMassiv[n].number then

               f:=false//Если клавиша нажате верно

             else

               begin   //Если не верно, то считаем и выводим ошибку

                 inc(Oshibki);

                 Gotoxy(1,2);

                 Write(‘Ошибки — ‘,Oshibki);

               end;

          end;

      end;

//Стираем предлагаемую клавишу, палец и убираем подсветку с экранной клавиатуры     

    gotoxy(LatMassiv[n].x-1,LatMassiv[n].y);

    write(‘ ‘,chr(LatMassiv[n].number-32),‘ ‘);

    gotoxy(40,9);

    ClearLine;

    GotoXY(1,14);

    ClearLine;

    sleep(200);//Делаем небольшуюу паузу

  end;

end;

begin

//Инициализация программы

  CRT.SetWindowTitle(‘Клавиатурный тренажёр’);

  HideCursor;

  ZapolnenieLatMassiv;

  Oshibki:=0;

  TextBackground(7);

  clrscr;

  TextColor(black);

end.

=========================================================================

Program KlavTren;

Uses CRT,MKlavTren;

begin

//Для примера два уровня

  for var i:=1 to 2 do

    begin

      clrScr;

      gotoxy(35,12);

      write(‘Уровень ‘,i,‘.’);

      sleep(2000);

      clrScr;

      Gotoxy(1,2);

      Write(‘Ошибки — ‘,Oshibki);

      WriteLatKlav;

      gotoxy(36,1);

      write(‘Уровень ‘,i);

      TextBackground(7);

      LatLevel(i*2);

    end;

  ClrScr;

  GoToXY(33,11);

  Write(‘Поздравляем!!!’);

  GoToXY(15,13);

  Write(‘Вы прошли клавиатурный тренажёр, совершив ‘,Oshibki,‘ ошибок.’);

  readln;

end.

_________________________________________________________________________

Для экономии бумаги я не стал приводить заполнение всего массива латинских клавиш. А так же не стал прописывать уровень тренировки русских букв. Процедура будет точно такая же, как и для латинских букв, только в ней необходимо будет использовать массив русских клавиш.

В конце параграфа в задачах будет предложено дописать этот клавиатурный тренажёр с учётом некоторых аспектов, которые так же будут приведены. Настоятельно рекомендую сделать это, и с помощью данного тренажёра научиться набирать текст не глядя в клавиатуру. Так же можете использовать и другой тренажёр. Думаю, их немало можно найти в просторах Интернета.

По началу будет не привычно не смотреть в клавиатуру, тем не менее, постепенно вы привыкните и потом вам будет не непривычно уже смотреть в неё. Уверяю вас, помимо того, что не глядя набирать быстрее это ещё и гораздо менее утомительно.

Игра «Гонки».

Плюс к тому, что мы написали клавиатурный тренажёр. Предлагаю написать игру под названием «Гонки». Это даст нам хороший опыт по программированию. Разберём весь процесс работы над такой программой поэтапно.

Для игры нам понадобятся следующие элементы:

  • трасса, которая должна двигаться относительно экрана;
  • машина, которая должна оставаться на месте относительно экрана и перемещаться влево, вправо относительно трассы;
  • препятствия, которые должны двигаться вместе с трассой, и которые необходимо будет объезжать.

Движущаяся трасса. Трассу обозначим с помощью левой и правой границы. Границы будут состоять из символов «|», примерно следующим образом:

   |         |

   |         |

   |         |

   |         |

   |         |

Эффект движения трассы создадим за счёт движения символов вниз. Для того, что бы было ощущение реального движения, сделаем на одну строчку с символами две пустых строчки. Через определённый промежуток времени будем стирать весь экран и перерисовывать трассу, при этом символы должны опуститься на одну строчку вниз.

Так как размер консольного окна при разворачивании на весь экран имеет размеры 80х50 символов, то зададим изначальный размер окна с помощью процедуры:

  SetWindowSize(80,50);

Так как символы будут находиться в каждой четвёртой строчке, то координату у для прорисовки нужно увеличивать каждый раз на 3. Когда координата станет больше 50, то из неё необходимо будет вычесть 50. Для того, что бы каждый раз начинать прорисовку не с первой строчки, а со второй или с третьей необходима переменная, которая будет хранить позицию, с которой начиналась прорисовка в предыдущий раз. Назовём  её yTrassa. Тогда в первом случае yTrassa будет равна 0. Во втором случае yTrassa=1, в третьем yTrassa=2.

Всего у нас получилось 3 повторяющиеся строчки. Следовательно, для прорисовки всей трассы необходимо проходов. При этом если y станет больше 50, то проход необходимо пропустить.

После всего вышесказанного можно написать следующий код:

program Trassa;

uses CRT;

var yTrassa:byte;

procedure DrowTrassa;

var y:byte;

begin

  y:=1+yTrassa;

  for var i:=1 to 17 do

    begin

      GotoXY(20,y);

      write(‘|’);

      GotoXY(60,y);

      write(‘|’);

      y:=y+3;

      if y>50 then break;

    end;

end;

begin

  SetWindowSize(80,50);

  yTrassa:=0;

  while true do

    begin

      if yTrassa=3 then yTrassa:=0;

      DrowTrassa;

      Sleep(600);

      ClrScr;

      Inc(yTrassa);

    end;

end.

___________________________________________

Препятствие. Препятствие может состоять из строчки 10 дефисов: «———-». Препятствие должно появляться между границами трассы в разных местах случайным образом. Для этого создадим переменную xTr, значение которой будем получать с помощью процедуры random(20,40). Двадцать и сорок числа не случайные. 20 позиция левого края трассы. 40 правая позиция трассы за вычетом 10 символов препятствия.

Для движения препятствия вместе с трассой создадим переменную yTr. Когда данная переменная станет больше 50, делаем её равной единице и присваиваем новое значение переменной xTr. Для прорисовки трассы напишем следующую процедуру:

procedure DrowPr;//Рисуем препятствие

begin

  if yPr>50 then

    begin

     yPr:=1;

     xPr:=Random(20,40);

    end;

  GotoXY(xPr,yPr);

  write(‘———————‘);

  Inc(yPr);

end;

Машина. С помощью символов Машину можем нарисовать следующим образом:

  ___

0|___|0

 |   |

 |___|

0|___|0

Она должна находиться внизу трассы и перемещаться влево и вправо относительно трассы, не выходя за её пределы. Для прорисовки машины создадим процедуру DrowCar и глобальную переменную xCar, которая будет хранить позицию, в которой находится машина.

Код процедуры DrowCar будет выглядеть следующим образом:

procedure DrowCar;

begin

  GotoXY(xCar,45);  write(‘  ___  ‘);

  GotoXY(xCar,46);  write(‘ |___| ‘);

  GotoXY(xCar,47);  write(‘0|   |0’);

  GotoXY(xCar,48);  write(‘ |___| ‘);

  GotoXY(xCar,49);  write(‘0|___|0’);

end;

Перемещение машины. Для перемещения машины нам необходима процедура, которая будет менять координату xCar в зависимости от того, какую клавишу нажал пользователь. Назовём эту процедуру Smena_xCar. Так как машина не должна выезжать за пределы трассы, то в конце процедуры необходимо проверить координату xCar, и если она выходит за границы трассы, то изменить её значение. Получим следующий код:

procedure Smena_xCar;

var cTemp:char;

begin

  if KeyPressed then

    begin

      cTemp:=ReadKey;

      if Ord(cTemp)=0 then

        begin

          cTemp:=ReadKey;

          case Ord(cTemp) of

            37: dec(xCar);

            39: inc(xCar);

          end;

        end;

      if xCar<=21 then xCar:=21;

      if xCar>=53 then xCar:=53;

    end;

end;

Суть игры. Используя все приведённые выше процедуры, мы уже можем написать игру, где будет двигаться трасса, появляться препятствия и где можно с помощью клавиатуры перемещать машину относительно трассы.

Осталось сделать игру интересной и захватывающей. Для этого необходимо при объезде каждого препятствия считать очки. Трасса должна двигаться с каждым разом всё быстрее и быстрее. Для этого создадим две переменные Ochki, для счёта очков и SleepTime, для ускорения движения трассы. А так же процедуру DrowOchki для вывода количества очков. Изменение этих переменных, а так же вызов этой процедуры необходимо произвести тогда, когда препятствие исчезает из вида, т.е. в первых строчках процедуры DrowPr, где проверяется переменная yPr, не стала ли она больше 50. С учётом вышесказанного процедуры DrowOchki и DrowPr будут выглядеть следующим образом:

procedure DrowOchki;

begin

  GotoXY(1,1);

  Write(‘Счёт ‘,Ochki);

end;

procedure DrowPr;//Рисуем препятствие

begin

  if yPr>50 then

    begin

     if SleepTime > 20 then SleepTime:=SleepTime-10;

     Inc(Ochki);

     yPr:=1;

     xPr:=Random(20,40);

    end;

  GotoXY(xPr,yPr);

  write(‘———————‘);

  Inc(yPr);

end;

Так же необходимо прописать остановку игры в том случае если машина наезжает на препятствие. Это событие может наступить тогда, когда переменная yPr будет равна 46, 47, 48 и 49, т.к. именно в этих координатах по y и находится машина. Хотя на самом деле машина начинается с координаты y=45, но визуально столкновение будет выглядеть реальнее если мы будем считать, что машина начинается с 46 координаты. Если машину воспринимать, как прямоугольник 7х4 символов, то условие наезда машины на препятствие будет выглядеть так:

(yPr>=46) and (yPr<=49) and ((xCar>(xPr-7)) and (xCar<=(xPr+19)))

Код основной программы. Далее необходимо написать код основной программы. Здесь необходимо произвести инициализацию всех переменных, затем войти в цикл, в котором будет происходить прорисовка всех элементов игры и изменение переменных. Для выхода из цикла необходимо проверять условие наезда машины на препятствие. При выходе из цикла необходимо вывести сообщение о том, что игра окончена. Для нашей игры код программы будет выглядеть следующим образом:

program Game_Gonka;

uses CRT;

var yTrassa,xCar,yPr,xPr:byte;

    SleepTime,Ochki:integer;

…………………………..

begin

  SetWindowCaption(‘Игра гонки’);

  SetWindowSize(80,50);

  yTrassa:=0;

  xCar:=36;

  yPr:=1;

  xPr:=Random(21,39);

  SleepTime:=200;

  Ochki:=0;

  while true do

    begin

      DrowTrassa;

      DrowCar;

      DrowPr;

      DrowOchki;

      if (yPr>=46) and (yPr<=49) and ((xCar>(xPr-7)) and (xCar<=(xPr+19))) then

        break;

      Sleep(SleepTime);

      Smena_xCar;

      Inc(yTrassa);

      if yTrassa=3 then yTrassa:=0;

      ClrScr;

    end;

   GotoXY(30,24);

   Write(‘Конец игры.’);

   readln;

end.

На месте строки с точками должны находиться процедуры, код которых был уже приведён.

В данном мы на аписали клавиатурный тренажёр и игру «Гонки». Тем самым мы научились применять все полученные ранее знания для написания полноценных программ.

Задачи.

1. Дописать клавиатурный тренажёр, учитывая следующие аспекты:

  • дописать массив латинских клавиш, причём необходимо ввести заглавные буквы;
  • ввести в экранную клавиатуру левую клавишу «Shift», которая должна подсвечиваться вместе с нужной клавишей, в случае если предлагается ввести заглавную букву. Левый «Shift» нажимается пятым пальцем левой руки, при этом те клавиши, которые нужно было нажимать пятым пальцем левой руки необходимо нажимать четвёртым пальцем левой руки. Можете поэкспериментировать и определить для себя оптимальное сочетание клавиш для нажатия заглавных букв;
  • перед началом тренировки необходимо предложить выбрать латинскую или русскую клавиатуру, соответственно написать процедуру RusLevel, процедуру рисования русской клавиатуры, и процедуру заполнения массива русских клавиш. В русской клавиатуре добавить клавишу с буквой «Ё», она нажимается пятым пальцем левой руки;
  • в случае если количество ошибок станет более 30% от количества предложенных клавиш, то вывести сообщение и начать тренировку с первого уровня.

2. Рассмотренный нами клавиатурный тренажёр предназначен для изучения расположения клавиш на клавиатуре и для того, что бы приучить пальцы нажимать нужные клавиши. Для того, что бы тренироваться набирать уже тексты, а не отдельные символы, можно написать клавиатурный тренажёр другого типа. Экран разделён на две половины верхнюю и нижнюю. В верхней части находится какой либо текст. В нижней части этот текст необходимо ввести. При этом в верхнем тексте необходимо подсвечивать символ, который должен в данный момент ввести пользователь. Так же необходимо считать ошибки.

3. Наберите код игры «Гонки» из данного параграфа. Детально его изучите. Допишите комментарии так, что бы можно было понять код, не читая текст данного параграфа.

4. Усовершенствуйте игру «Гонки», исходя из следующих тезисов:

  • необходимо создать стартовую страницу, которая будет показана после запуска программы. На этой странице необходимо вывести название игры, правила и предложить игроку ввести своё имя.
  • при наезжании машины на препятствии вывести сообщение о том, что игра закончена, и вывести список игроков с их результатами. Список должен быть отсортирован по результату. Имя игрока, который только, что играл должен быть выделен другим цветом. На этой же странице предложить играть снова или закрыть программу.
  • Игра должна быть закончена так же при наезде машины на край трассы.
  • При нажатии игроком клавиши «Esc» игра должна входить в режим паузы. При этом должно быть предложено выйти из игры вообще или продолжить игру. Реализовать это можно с помощью специальной процедуры, которая может быть вызвана в том месте кода, где идёт считывание нажатой клавиши, т.е. в процедуре Smena_xCar.
  • Изменить цвета у элементов игры: у фона, трассы, машины и препятствия.
  • Придумать и реализовать свои усовершенствования.

5.Придумайте и напишите свою игру.

Решение.

1. Решение третьей задачи оставляю на вашу самостоятельную работу, т.к. костяк программы уже есть, необходимо только её дописать.

2.

unit MklavTren_2;

uses CRT;

const ks=9;//Количество строк выводимого текста

var fText:Text;//Файловая переменная

    sFile:string;//Текстовый файл

    mText:array [1..ks] of string[80];//Массив строк

                                      //содержит текст для вывода

    sTek:string;//Текущая строка

    final:=0;//Считает строки после окончания текстового файла

//Читаем строку из файла, если файл закончен,то строка равна »

function chteniestroki:string[80];

var sTemp:string;

    cTemp:char;

begin

  if not Eof(fText) then

    begin

      for var i:=1 to 80 do

        begin

          if not Eoln(fText) then

              begin

                read(fText,cTemp);

                sTemp:=sTemp+cTemp;

              end

            else

              begin

                if not Eof(fText) then readln(fText,cTemp);

                break;

              end

        end;

      chteniestroki:=sTemp;

    end

   else

    begin

      chteniestroki:=»;

      Inc(final);

    end

end;

//»Прокручиваем» текст вверх в массиве mText

procedure SmenaChlenov;

begin

  for var i:=1 to (ks-1) do mText[i]:=mText[i+1];

  mText[ks]:=chteniestroki;

end;

//Вывод текста на экран

procedure VivodTexta;

begin

  gotoxy(1,1);

  for var i:=1 to ks do

   begin

    writeln(mText[i]);

    if Length(mText[i])=80 then GotoXY(1,WhereY-1);

   end;

end;

procedure ObnovlenieTexta;

begin

  SmenaChlenov;

  VivodTexta;

end;

//Подсвечивание нужного символа в тексте

procedure PodsvechSimvola(simvol:byte);

var x,y:byte;

begin

  x:=WhereX;

  y:=WhereY;

  TextBackground(Red);

  GotoXY(simvol,5);

  Write(sTek[simvol]);

  TextBackground(Black);

  GotoXY(x,y);

end;

//Убирание подсветки с симолоа в тексте

procedure UbiraniePodsvetki(simvol:byte);

var x,y:byte;

begin

  x:=WhereX;

  y:=WhereY;

  TextBackground(Black);

  GotoXY(simvol,5);

  Write(sTek[simvol]);

  GotoXY(x,y);

end;

procedure VivodOshibok(o:integer);

var x,y:byte;

begin

  x:=WhereX;

  y:=WhereY;

  GotoXY(35,12);

  write(‘             ‘);

  Sleep(200);

  GotoXY(35,12);

  Write(‘Ошибок — ‘,o);

  GotoXY(x,y);

end;

function ReadSimvol:char;//Читаем нажатый символ

begin

  while not KeyPressed do;

  ReadSimvol:=ReadKey;

end;

end.

=========================================================================

Program KlavTren_2;

Uses CRT,MKlavTren_2;

var c:char;//Для чтения нажатого символа

    simvol,//порядковый номер текущего символа в строке

    oshibki:byte;//Для счёта ошибок

procedure VvodSrtoki;

var b:boolean;//нужна для выхода из цикла

              //Равна false, когда строка введена

begin

  sTek:=mText[5];

  GotoXY(1,15);

  b:=true;

  simvol:=1;

  while b do

    begin

     PodsvechSimvola(simvol);

     c:=readSimvol;

     if c=sTek[simvol] then

       begin

        UbiraniePodsvetki(simvol);

        Inc(simvol);

        write(c);

       end

      else

       begin

        Inc(oshibki);

        VivodOshibok(oshibki);

       end;

     if simvol>Length(sTek) then b:=false;

    end;

end;   

begin

  SetWindowCaption(‘Клавиатурный тренажёр 2’);

//Предлагаем пользователю выбрать какой-либо вариант текста

  while true do

   begin

    Writeln(‘Вы открыли клавиатурный тренажёр!’);

    Writeln(‘Выберите текст для набора:’);

    Writeln(‘1 — «Операционная система MS DOS»‘);

    Writeln(‘2 — «Команды MS DOS»‘);

    read(c);

    case c of

      ‘1’:sFile:=‘MS DOS.txt’;

      ‘2’:sFile:=‘Команды DOS.txt’ ;

     end;

    if (c=‘1’) or (c=‘2’) then break;

    ClrScr;

   end;

//Собственно сама программа

  Assign(fText,sFile);

  Reset(fText);

//Заполняем первые строки текста

  for var i:=6 to ks do mText[i]:=chteniestroki;

//Входим в цикл набора текста

  while final<5 do

    begin

      ClrScr;

      ObnovlenieTexta;

      VivodOshibok(oshibki);     

      GotoXY(1,17);

      if mText[5]=» then continue;

      VvodSrtoki;

    end;

  Close(fText);

  writeln; 

  writeln(‘Конец’);

  readln;

end.

_________________________________________________________________________

3.4.5. Эти задания сделайте самостоятельно.

uses
  graphABC, ABCobjects, timers;



var
  f, fn: text;
  t,check: Timer;
  base_color, cgr: Color;
  
  ug, time_play_sec,take_speed,time: real;
  login, Str, str2, str3, st1, ch, password, zs, ks: string;
  chapter, level, n, xgr, ygr, rgr, x_power, y_power,spin, time_play_sec2,chapter_test: integer;  
  xb, yb, xg, yg, power, ww, wh, shot, time_play_min, shot_max,level_test: integer;
  
  Basa: RegularPolygonABC;
  show4, target, target_bad: ObjectABC;
  show, show2, show3, registr_but, login_but, status_box: RectangleABC;
  Star, sun: StarABC;
  show_pos: CircleABC;
    
  Average_ugol: array of integer;
  Average_power: array of integer;
  mb: array[1..62] of string;
  ground: array [1..9] of CircleABC;
  panel: array [1..5] of RectangleABC;
  
  lvlup_b, play, Cont, login_next, regist_next, from_0, from_6: boolean;

procedure pfile;
begin
  Assign(fn, login + '.txt');
  append(fn);
  writeln(fn, '0');
  write(fn, '0');
  close(fn);
end;

procedure prewrite;
begin
  Assign(f, login + '.txt');
  Rewrite(f);
  writeln(f, level);
  Write(f, chapter);
  Close(f);
end;

procedure pread;
var
  level_s, chapter_s: string;
begin
  Assign(f, login + '.txt');
  Reset(f);
  repeat
    Readln(f, level_s);
    level := StrToInt(level_s);
    readln(f, chapter_s);
    chapter := StrToInt(chapter_s);
  until Eof(f);
  Close(f);
end;

procedure pgenerate;
begin
  var show_login: RectangleABC := new RectangleABC(0, 51, 150, 35, clorangeRed);
  show_login.Text := 'Ваш логин: ' + Login;
  st1 := 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789.';
  for var it := 1 to st1.length - 1 do 
  begin
    mb[it] := st1[it];
  end;
  status_box.Text := 'Введите пароль: ';
  readln(ch);
  password := ch;
  status_box.text := 'Вы создали нового пользователя!';
  show_login.Destroy; 
  pfile;
end;

procedure pcreate;
begin
  var show_login: RectangleABC := new RectangleABC(0, 51, 150, 25, clorangeRed);
  assign(F, 'users.txt');
  append(f);
  close(f);
  reset(f);
  show_login.text := 'Введите логин: ';
  status_box.Text := 'Введите логин: ';
  readln(login);
  while not eof(f) do
  begin
    if (str <> str2) then eof(f);
    readln(f, str);
    if pos(login, str) > 0 then begin
      str2 := str;
      readln(f, str);
      str3 := str;
      if (str <> str2) then eof(f);
    end;
  end;
  close(f);
  if login = str2 then begin
    status_box.Text := 'Это имя уже занято!';
    regist_next := false;
  end
  else begin
    Append(F);
    status_box.text := 'Помощь: Если ввести /gen, то пароль будет сгенерирован автоматически.';
    pgenerate;
    zs := '';
    ks := ',.!@?-:;+';
    for var i := 1 to password.Length do 
    begin
      n := pos(password[i], ks);
      zs := zs + inttostr(n);
    end; 
    zs := '';
    ks := ',.!@?-:;+Zqazwsxedc90rfvtgbhnu7jAmiklop345QWERTYSXDCyFVG1BUHNMJI2OPKL68';
    for var i := 1 to password.Length do 
    begin
      n := pos(password[i], ks);
      zs := zs + inttostr(n);
    end;
    password := zs;
    writeln(f, login);
    writeln(f, password);
    close(f); 
  end;
  show_login.Destroy;
end;

procedure plogin;
begin
  Assign(f, 'users.txt');
  append(f);
  Close(f);
  Assign(f, 'users.txt');
  reset(f);
  var show_login: RectangleABC := new RectangleABC(0, 51, 150, 35, clorangeRed);
  show_login.Text := 'Ваш логин: ';
  status_box.Text := 'Введите логин';
  readln(Login); 
  show_login.Text += Login;
  while not eof(f) do
  begin
    if (str <> str2) then eof(f);
    readln(f, str);
    if pos(login, str) > 0 then begin
      str2 := str;
      readln(f, str);
      str3 := str;
      if (str <> str2) then eof(f);
    end;
  end;
  status_box.Text := 'введите пароль';
  readln(password);
  zs := '';
  ks := ',.!@?-:;+Zqazwsxedc90rfvtgbhnu7jAmiklop345QWERTYSXDCyFVG1BUHNMJI2OPKL68';
  for var i := 1 to password.Length do 
  begin
    n := pos(password[i], ks);
    zs := zs + inttostr(n);
  end;
  password := zs;
  if (str3 = password) then begin
    status_box.Text := 'Выполнен вход в учетную запись: ' + Login;
  end
  else begin status_box.Text := 'Ошибка входа: Неверный логин или пароль'; login_next := false; end;
  close(f);
  show_login.Destroy;
end;

procedure stats;
var
  x, y, w, h: integer;
begin
  x := 0;
  y := wh - 30;
  w := 160;
  h := 30;
  for var i := 1 to 5 do //Создаем нижнюю панель
  begin
    if i < 5 then panel[i] := new RectangleABC(x, y, w + 1, h, RGB(120 + 15 * i, 50 + level * 5, 100));
    if i = 5 then panel[i] := new RectangleABC(x, y, w, h, RGB(120 + 15 * i, 50 + level * 5, 100));
    panel[i].BorderWidth := 2;
    x += w;
  end;
end;

procedure Start;
begin
  SetWindowSize(800, 600);
  ClearWindow(clWhite);
  wh := WindowHeight;
  ww := WindowWidth;
  if level = 0 then level := 0;
  if chapter = 0 then chapter := 0;
  Window.IsFixedSize := true;
  sun := new StarABC(35, 35, 20, 25, 16, clGold);
  SetLength(Average_power, 0);
  SetLength(Average_ugol, 0);
  shot := 0;
  time_play_min := 0;
  time_play_sec := 0;
end;

procedure basegen(xb, yb: integer);//создаем базу
begin
  Line(xb - 50, yb, xb + 50, yb);
  Line(xb, yb - 50, xb, yb + 50);
  Line(xb - 50, yb - 1, xb + 50, yb - 1);
  Line(xb - 1, yb - 50, xb - 1, yb + 50);
  Line(xb - 50, yb, xb + 50, yb);
  Line(xb, yb - 50, xb, yb + 50);
  Line(xb - 50, yb - 1, xb + 50, yb - 1);
  Line(xb - 1, yb - 50, xb - 1, yb + 50);
  basa := new RegularPolygonABC(xb, yb, 30, 5, base_color);
end;

procedure mapgen(level_p: integer);//генерируем карту
begin
  target_bad := new RectangleABC(0, 0, 0, 0, clWhite);
  shot_max := 5;
  xb := 100;
  yb := 300;
  xgr := 0;
  ygr := 530;
  rgr := 100;
  cgr := clLavender;
  for var i := 1 to 9 do 
  begin
    ground[i] := new CircleABC(xgr, ygr, rgr, cgr);
    ground[i].bordered := false;
    xgr += 100;
  end;
  xgr := 0;
  for var i := 1 to 9 do 
  begin
    Arc(xgr, ygr - 1, 100, 60, 120);
    xgr += 100;
  end;
  basegen(xb, yb);//добавляем базу
  
  if level_p=-2 then begin target := new rectangleABC(650, 100, 10, 300, clRed); end;
  
  
  if level_p = 0 then begin
    from_0 := true;
    show := new RectangleABC(100, 0, ww - 100, 20, clwheat);
    show.Text := 'Кликните в любом месте мышкой и удерживая перетащите в любое другое место, так вы сможете выбрать силу.';
    show2 := new RectangleABC(100, 20, ww - 100, 20, clwheat);
    show2.Text := 'Внизу на панеле отображается ваши текущие угол и сила, При соприкосновении с поверхностью ядро взрывается';
    show3 := new RectangleABC(100, 40, ww - 100, 20, clwheat);
    show4 := new RectangleABC(0, 60, ww, 20, cllime);
    show3.Text := 'На каждом уровне есть ограниченное кол-во выстрелов, если вы не успели попасть в цель, вы переходите на уровень назад';
    show4.text := 'Чтобы пройти уровень надо попадать по красным мишеням. Сейчас попадите в красную стенку';
    show3.TextScale := 0.9;
    target := new rectangleABC(650, 100, 10, 300, clRed);
  end;
  stats;//добавляем нижнюю панель
  panel[3].Text := 'Глава: ' + IntToStr(chapter);
  panel[4].Text := 'Уровень: ' + IntToStr(level); 
  if level_p = 1 then begin
    if (from_0 = true) then begin
      show.Destroy;
      show2.Destroy;
      show3.Destroy;
      show4.Destroy;
    end;
    target := new CircleABC(300, 200, 30, clRed);
  end;
  if level > 1 then panel[5].Text := 'Выстрел ' + IntToStr(shot) + ' из ' + IntToStr(shot_max);  
  if (level_p = 2) then target := new CircleABC(400, 400, 30, clRed);
  if (level_p = 3) then target := new CircleABC(100, 50, 30, clRed);
  if (level_p = 4) then target := new CircleABC(500, 110, 30, clRed);
  if (level_p = 5) and (from_6 = false) then target := new CircleABC(700, 330, 20, clRed);
  if (level_p = 5) and (from_6 = true) then begin show.Destroy; target := new CircleABC(700, 330, 20, clRed); end;
  if (level_p = 6) then begin
    from_6 := true; show := new RectangleABC(100, 0, ww - 100, 20, clwheat);
    show.Text := 'Черные цели перенаправляют вас сразу на уровень назад!';
    target := new CircleABC(720, 350, 30, clred); target_bad := new CircleABC(720, 150, 30, clblack);
  end;
  
  time_play_min := 0;
  time_play_sec := 0;
  if level > 6 then begin
    if (from_6 = true) then begin
      from_6 := false;
      show.Destroy;
    end;
    target := new CircleABC(Random(100, ww - 50), Random(100, wh - 250), 30, clRed);
  end;
end;

procedure lvldown;
begin
  target.Destroy;
  target_bad.Destroy;
  ClearWindow(clWhite);
  var stat_box := new RoundRectABC(10, 10, ww - 20, wh - 20, 15, clslateblue);
  stat_box.BorderWidth := 2;
  var box: array[1..5] of RoundRectABC;
  var x_box, y_box: integer;
  x_box := 20;
  y_box := 20;
  for var i := 1 to 5 do 
  begin
    box[i] := new RoundRectABC(x_box, y_box, ww - 40, 100, 15, RGB(100 + 20 * i, 100, 100));
    box[i].BorderWidth := 2;
    y_box += 105;
    if i = 1 then begin box[i].Color := clred; box[i].Text := 'Вы не прошли уровень: ' + IntToStr(level); end;
    if i = 2 then box[i].Text := 'Средняя сила: ' + IntToStr(Round(Average_power.Average)) + 'p';
    if i = 3 then box[i].Text := 'Средний угол: ' + IntToStr(Round(Average_ugol.Average));
    if i = 4 then box[i].Text := 'Выстрелов: ' + IntToStr(shot); 
    if i = 5 then begin
      if time_play_min = 0 then box[i].Text := 'Время: ' + time_play_sec.ToString + 'c.'
      else box[i].Text := 'Время: ' + time_play_min.ToString + 'm. ' + time_play_sec.ToString + 'c.';
    end;
  end;
  Sleep(5000);
  for var i := 1 to 5 do box[I].Destroy;
  stat_box.destroy;
  level -= 1;
  SetLength(Average_power, 0);
  SetLength(Average_ugol, 0);
  shot := 0;
  prewrite;
  mapgen(level);
  Basa.RedrawNow;
  for var i := 1 to 5 do panel[i].RedrawNow;
  sun.RedrawNow;
  for var i := 1 to 9 do ground[i].RedrawNow;
end;

procedure lvlup;
begin
  lvlup_b := false;
  ClearWindow(clWhite);
  
  target.Destroy;
  target_bad.Destroy;
  var stat_box := new RoundRectABC(10, 10, ww - 20, wh - 20, 15, clslateblue);
  stat_box.BorderWidth := 2;
  var box: array[1..5] of RoundRectABC;
  var x_box, y_box: integer;
  x_box := 20;
  y_box := 20;
  for var i := 1 to 5 do 
  begin
    box[i] := new RoundRectABC(x_box, y_box, ww - 40, 100, 15, RGB(100, 100 + 20 * i, 170));
    box[i].BorderWidth := 2;
    y_box += 105;
    if i = 1 then begin box[i].Color := cllime; box[i].Text := 'Вы прошли уровень: ' + IntToStr(level); end;
    if i = 2 then box[i].Text := 'Средняя сила: ' + IntToStr(Round(Average_power.Average)) + 'p';
    if i = 3 then box[i].Text := 'Средний угол: ' + IntToStr(Round(Average_ugol.Average));
    if i = 4 then box[i].Text := 'Выстрелов: ' + IntToStr(shot); 
    if i = 5 then begin
      if time_play_min = 0 then box[i].Text := 'Время: ' + time_play_sec.ToString + 'c.'
      else box[i].Text := 'Время: ' + time_play_min.ToString + 'm. ' + time_play_sec.ToString + 'c.';
    end;
  end;
  Sleep(5000);
  for var i := 1 to 5 do box[I].Destroy;
  stat_box.destroy;
  level += 1;
  if (level = 1) and (chapter = 0) then chapter += 1;
  if (level mod 6 = 0) and (level > 1) then chapter += 1;
  SetLength(Average_power, 0);
  SetLength(Average_ugol, 0);
  shot := 0;
  prewrite;
  mapgen(level);
  Basa.RedrawNow;
  for var i := 1 to 5 do panel[i].RedrawNow;
  sun.RedrawNow;
  for var i := 1 to 9 do ground[i].RedrawNow;
  
end;

function myfunc(xr, yr, p, ug: real): real;//функция полета
var
  t: real;
begin
  play := true;
  t := 0;//Время
  xg := 0;//Коориданата Х
  yg := 0;//Коориданата У
  Star := new StarABC(Round(xr), Round(yr), 20, 10, 10, clRandom);//Создаем объект-ядро
  if level < 0 then Check.Start;
  repeat
  if level < 0 then TextOut(0,500,'ПРОРИСОВКА: '+time_play_sec2.ToString+' ');
    xg := Round((xr) + ((p * t * cos(ug)) / 2));
    yg := Round((yr) - (p * t * sin(ug) - (9.8 * t * t / 2)));
    xg -= 2;
    Star.MoveTo(xg, yg);//перемещения ядра в (xg,yg)
    Star.Angle += spin;//Вращаем ядро
    MoveTo(xg, yg);
    PutPixel(xg, yg, clRed);//рисуем путь
    t += time;//Прибавляем время
    sleep(2);//Задержка в 2 милисекунды 
    if (Star.Intersect(target) = true) then lvlup_b := true;
    if (Star.Intersect(target_bad) = true) then begin lvlup_b := false; shot += shot_max * 2; end;
    if (Star.Intersect(target) = true) then take_speed := time_play_sec2;
  until (star.Intersect(ground[1]) = true) or (star.Intersect(ground[2]) = true) 
   or (star.Intersect(ground[3]) = true) or (star.Intersect(ground[4]) = true)
    or (star.Intersect(ground[5]) = true) or (star.Intersect(ground[6]) = true)
     or (star.Intersect(ground[8]) = true) or (star.Intersect(ground[8]) = true)
      or (star.Intersect(ground[9]) = true) or (xg > ww + 10) or (Star.Intersect(target) = true)
      or (star.Intersect(target_bad) = true);
     if level < 0 then  check.Stop;
     if level < 0 then  time_play_sec2:=0;
  Star.Destroy;//убираем звезду
  shot += 1;
  if level > 1 then panel[5].Text := 'Выстрел ' + IntToStr(shot) + ' из ' + IntToStr(shot_max);
  
  //подсчет средних
  setLength(Average_ugol, shot);
  Average_ugol[shot - 1] := Round(RadToDeg(ug));
  setLength( Average_power, shot);
  Average_power[shot - 1] := Round(power);
  if (shot > shot_max - 1) and (lvlup_b = false) and (level > 1) then lvldown;
  if (level > 0) then if (lvlup_b = true) and (shot < shot_max + 1) then lvlup;
  if (level < 2) and (lvlup_b = true) then lvlup;
  myfunc := t;
  Play := false;
end;

procedure MouseMove(xm, ym, mb: integer);
var
  a, b, c: real;
begin
  a := Abs(xm - xb);
  b := Abs(ym - yb);
  c := Sqrt(Sqr(a) + Sqr(b));
  ug := (arcsin(b / c));
  panel[1].Text := 'Угол: ' + IntToStr(Round(RadToDeg(ug)));
  if mb = 1 then  panel[2].Text := 'Сила: ' + IntToStr(Round(sqrt(sqr((xm - x_power)) + sqr((ym - y_power))))) + 'p';//Показываем силу
end;

procedure MouseDown(xm, ym, mb: integer);
begin
  show_pos := new CircleABC(xm, ym, 2, clwheat);
  x_power := xm;
  y_power := ym;
end;

procedure MouseUp(xm, ym, mb: integer);
var
  a, b, c: real;
begin
  a := Abs(xm - xb);
  b := Abs(ym - yb);
  c := Sqrt(Sqr(a) + Sqr(b));
  ug := (arcsin(b / c));
  power := Round(sqrt(sqr((xm - x_power)) + sqr((ym - y_power))));//Высчитывем силу
  panel[1].FontColor := clWhite;
  panel[1].text := 'Угол полета: ' + IntToStr(Round(RadToDeg(ug)));
  panel[2].FontColor := clWhite;
  panel[2].text := 'Сила полета: ' + IntToStr(Round(power)) + 'p';
  if (mb = 1) and (play = false) and (power > 0) then myfunc(xb, yb, power, ug);//запускаем ядро
  panel[2].FontColor := clBlack;
  panel[1].FontColor := clBlack;
  panel[2].Text := '';
  show_pos.Destroy;
end;

procedure rotate;
begin
  sun.Angle += 1;
  time_play_sec += 0.5;
  if time_play_sec = 60.0 then begin time_play_min += 1; time_play_sec := 0; end;
end;

procedure MouseDownS(xm, ym, mb: integer);
begin
  if mb = 1 then base_color := GetPixel(xm, ym);
end;

procedure Hello;
begin
  SetWindowSize(800, 600);
  Window.IsFixedSize := true;
  var start1 := new RoundRectABC(8, 8, windowwidth - 16, WindowHeight - 15, 10, clLavender);
  start1.BorderWidth := 3;
  var start1_name := new RoundRectABC(15, 15, windowwidth - 30, 50, 10, clGreenYellow);
  start1_name.BorderWidth := 2;
  start1_name.Text := 'Добро пожаловать, ' + Login + '!';
  Sleep(200);
  var start1_color := new RoundRectABC(15, 70, WindowWidth - 30, 50, 10, clFirebrick);
  start1_color.BorderWidth := 2;
  start1_color.Text := 'Выберите цвет базы';
  for var iy := 1 to 18 do 
  begin
    Rectangle(50, 105 + iy * 25, 151, 135 + iy * 25);
    FloodFill(52, 105 + iy * 25 + 2, clRandom);
  end;
  for var iy := 1 to 18 do 
  begin
    Rectangle(50 + 100 * 1, 105 + iy * 25, 151 + 100 * 1, 135 + iy * 25);
    FloodFill(52 + 100 * 1, 105 + iy * 25 + 2, clRandom);
  end;
  for var iy := 1 to 18 do 
  begin
    Rectangle(50 + 100 * 2, 105 + iy * 25, 151 + 100 * 2, 135 + iy * 25);
    FloodFill(52 + 100 * 2, 105 + iy * 25 + 2, clRandom);
  end;
  for var iy := 1 to 18 do 
  begin
    Rectangle(50 + 100 * 3, 105 + iy * 25, 151 + 100 * 3, 135 + iy * 25);
    FloodFill(52 + 100 * 3, 105 + iy * 25 + 2, clRandom);
  end;
  for var iy := 1 to 18 do 
  begin
    Rectangle(50 + 100 * 4, 105 + iy * 25, 151 + 100 * 4, 135 + iy * 25);
    FloodFill(52 + 100 * 4, 105 + iy * 25 + 2, clRandom);
  end;
  for var iy := 1 to 18 do 
  begin
    Rectangle(50 + 100 * 5, 105 + iy * 25, 151 + 100 * 5, 135 + iy * 25);
    FloodFill(52 + 100 * 5, 105 + iy * 25 + 2, clRandom);
  end;
  for var iy := 1 to 18 do 
  begin
    Rectangle(50 + 100 * 6, 105 + iy * 25, 151 + 100 * 6, 135 + iy * 25);
    FloodFill(52 + 100 * 6, 105 + iy * 25 + 2, clRandom);
  end;
  OnMouseDown := MouseDownS;
  var timerShow := new RoundRectABC(WindowWidth - 55, 70, 40, 50, 10, clcyan);
  timerShow.BorderWidth := 2;
  timerShow.Text := '3';
  Sleep(1000);
  timerShow.Text := '2';
  Sleep(1000);
  timerShow.Text := '1';
  Sleep(1000);
  timerShow.Destroy;
  start1.Destroy;
  start1_color.Destroy;
  start1_name.Destroy;
end;

procedure MouseDownBeg(xm, ym, mb: integer);
begin
  if login_but.PtInside(xm, ym) = true then login_next := true;
  if registr_but.PtInside(xm, ym) = true then regist_next := true;
end;
procedure timer_check;
begin
  time_play_sec2 += 1;
end;

begin
base_color:=clRandom;
  SetWindowCaption('TimeKiller v0.2');
  target_bad := new RectangleABC(0, 0, 0, 0, clWhite);
  SetWindowSize(800, 600);
  cont := false;
  from_0 := false;
  from_6 := false;
  OnMouseDown := MouseDownBeg;
  var main: RectangleABC := new RectangleABC(0, 0, WindowWidth, windowheight, clLavender);
  login_but := new RectangleABC(0, 0, 401, 50, clolive);
  registr_but := new RectangleABC(399, 0, 400, 50, clOliveDrab);
  login_but.BorderWidth := 2;
  registr_but.BorderWidth := 2;
  login_but.FontColor := clwhite;
  registr_but.FontColor := clgold;
  login_but.Text := 'Войти';
  registr_but.Text := 'Зарегистрироваться';
  status_box := new RectangleABC(0, WindowHeight - 30, WindowWidth, 30, clgold);
  status_box.BorderWidth := 2;
  status_box.Color := ARGB(120, 255, 215, 0);
  status_box.Text := 'Вам необходимо войти или зарегистрироваться';
  repeat
    Sleep(1000);
    if login_next = true then begin plogin; end; 
    if regist_next = true then begin pcreate; end; 
  until (login_next = true) or (regist_next = true);
  pread;
  cont := true;
  if Cont = true then begin
    main.Destroy;
    status_box.Destroy;
    login_but.Destroy;
    registr_but.Destroy;
    Hello;
    start;
    
    TextOut(0,0,'Подождите идет загрузка данных. Прорисовка.');
     time := 0.02;
     spin := 1;
    time_play_sec := 0;
    level_test:=level;
    chapter_test:=chapter;
    chapter:=0;
    level:=-2;
    mapgen(level); 
   
    Check := new Timer(1, timer_check);
    
    myfunc(xb, yb, 200, Pi / 10);//Проверка медленной скорости;
   
    if take_speed > 100 then begin time := 0.08; spin := 2; end;
    check.Stop; 
    Check := new Timer(1, timer_check);
    time_play_sec := 0;
    target.Destroy;
    level:=-2;
    mapgen(level);
    TextOut(0,0,'Подождите идет загрузка данных. Прорисовка.');
    myfunc(xb, yb, 200, Pi / 10);//Проверка быстрой скорости;
   
    if take_speed < 50 then begin time := 0.02; spin := 1; end;
    target.Destroy;
    level:=level_test;
    chapter:=chapter_test;
  
    
    mapgen(level); 
    T := new Timer(500, rotate);
    T.Start;
    OnMouseMove := MouseMove; 
    OnMouseDown := MouseDown;
    OnMouseUp := MouseUp;
  end;
end.
uses ABCObjects,Events,GraphABC,Timers,Utils;
 
var
  kLeftKey,kRightKey: boolean;
  kSpaceKey: integer;
  Player: RectangleABC;
  t: integer;
  EndOfGame: boolean;
  Enemies: TextABC;
  StaticObjectsCount: integer;
  NewGame: TextABC;
  Wins,Falls: integer;
  WinsABC,FallsABC: TextABC;
  r1: RectangleABC;
 
type
  KeysType=(kLeft,kRight);
  Pulya=class(CircleABC)
    constructor Create(x,y: integer);
    begin
      inherited Create(x,y,5,clRed);
      dx:=0; dy:=-5;
    end;
    procedure Move;
    var j: integer;
    begin
      inherited Move;
      if Top<0 then
        Visible:=False;
      for j:=StaticObjectsCount+1 to ObjectsCount do
        if (Objects[j]<>Self) and Intersect(Objects[j]) then
        begin
          Objects[j].Visible:=False;
          Visible:=False;
        end;
    end;
  end;
  Enemy=class(RectangleABC)
    constructor 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 Move;
    begin
      if Random(2)<>0 then Exit;
      if Random(10)=0 then dy:=5;
      if (Left<0) or (Left+Width>WindowWidth) or (Random(30)=0) then
        dx:=-dx;
      inherited Move;
      if dy<>0 then dy:=0;
      if Top>WindowHeight-50 then
        EndOfGame:=True;
    end;
  end;
 
function NumberOfEnemies: integer;
var i: integer;
begin
  Result:=0;
  for i:=1 to ObjectsCount do
    if Objects[i] is Enemy then
      Inc(Result);
end;
 
procedure CreateObjects;
var
  i: integer;
  r1: RectangleABC;
begin
  Player:=RectangleABC.Create(280,WindowHeight-30,100,20,clTeal);
  for i:=1 to 100 do
  begin
    r1:=Enemy.Create(Random(WindowWidth-50),40+Random(10),50);
    r1.TextVisible:=True;
    r1.Number:=i;
  end;
end;
 
procedure DestroyObjects;
var i: integer;
begin
  for i:=ObjectsCount downto StaticObjectsCount+1 do
    Objects[i].Destroy;
end;
 
procedure MoveObjects;
var i: integer;
begin
  for i:=StaticObjectsCount+2 to ObjectsCount do
    Objects[i].Move;
end;
 
procedure DestroyKilledObjects;
var i: integer;
begin
  for i:=ObjectsCount downto StaticObjectsCount+2 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 Timer1;
var
  i,j,n: integer;
  p: Pulya;
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
    p:=Pulya.Create(Player.Left+Player.Width div 2,Player.Top-10);
    kSpaceKey:=0;
  end;
  MoveObjects;
  DestroyKilledObjects;
  RedrawObjects;
  n:=NumberOfEnemies;
  Enemies.Text:='Врагов: '+IntToStr(n);
  if n=0 then
    EndOfGame:=True;
  if EndOfGame then
  begin
    StopTimer(t);
    if n>0 then
    begin
      Inc(Falls);
      FallsABC.Text:='Поражений: '+IntToStr(Falls);
      RedrawObjects;
      ShowMessage('Вы проиграли!');
      DestroyObjects;
      Enemies.Text:='Врагов: '+IntToStr(NumberOfEnemies);
      RedrawObjects;
    end
    else
    begin
      Inc(Wins);
      WinsABC.Text:='Побед: '+IntToStr(Wins);
      RedrawObjects;
      ShowMessage('Вы выиграли!');
      DestroyObjects;
      Enemies.Text:='Врагов: '+IntToStr(NumberOfEnemies);
      RedrawObjects;
    end;
  end;
end;
 
procedure MouseUp(x,y,mb: integer);
begin
  if NewGame.PTInside(x,y) then
    StartTimer(t);
end;
 
procedure KeyPress(Key: char);
begin
  if ((UpCase(Key)='G') or (UpCase(Key)='П')) and EndOfGame then
  begin
    EndOfGame:=False;
    StartTimer(t);
    CreateObjects;
    kSpaceKey:=2;
    kLeftKey:=False;
    kRightKey:=False;
  end;
end;
 
begin
  LockDrawingObjects;
  EndOfGame:=True;
  r1:=RectangleABC.Create(0,0,WindowWidth,38,clWhite);
  NewGame:=TextABC.Create(WindowWidth-180,5,14,clBlack,'G - Новая игра');
  Enemies:=TextABC.Create(10,5,14,clRed,'Врагов: '+IntToStr(NumberOfEnemies));
  WinsABC:=TextABC.Create(150,5,14,clRed,'Побед: '+IntToStr(Wins));
  FallsABC:=TextABC.Create(280,5,14,clRed,'Поражений: '+IntToStr(Falls));
  StaticObjectsCount:=ObjectsCount;
  Enemies.Text:='Врагов: '+IntToStr(NumberOfEnemies);
  OnKeyDown:=KeyDown;
  OnKeyPress:=KeyPress;
  OnKeyUp:=KeyUp;
  OnMouseUp:=MouseUp;
  t:=CreateTimer(10,Timer1);
  StopTimer(t);
  RedrawObjects;
end.

Понравилась статья? Поделить с друзьями:
  • Как написать игру на котлин
  • Как написать игру на джава скрипт
  • Как написать игру на денди
  • Как написать игру на ассемблере для zx spectrum купить
  • Как написать игру на айпад