Привета!
Задача формулировалась преподом довольно размыто, поэтому может присутствовать некоторая вольность в выполнении, что не может не радовать. Смысл в том, чтоб написать на Pascal (к сожалению) игру, в которой есть кораблики, соревнующиеся между собой Препод седой уже, кстати. Он хотел там видеть возможность выбора направления ветра и хода корабликов галсами при встречном ветре, но реализовать управление парусами, по-моему, слишком сложно, а как без этого галсами ходить? Поэтому реализация мне видится так: вид сверху на остров либо замкнутый кольцевой канал, один кораблик с мотором, цель игры - управляя корабликом стрелками пройти дистанцию за наименьшее время. Если у кого-то возникнет желание помочь или вдруг есть какие-то наработки, буду очень признателен.
Вот код:
program MAPA3M;Тут нарисованы берега "лагуны" с островом посередине, вид сверху. Кораблик обозначен коричневой точкой и управляется с клавиатуры, это пока все =/ Как видите, нету навыка работы с процедурами, пишется сложно =/
uses crt, graph;
var
Gd,Gm:integer;
posX,posY:integer;
ch:char;
procedure bereg;
begin
setcolor(yellow);
setfillstyle(7,yellow);
sector(280,200,0,360,100,50);
sector(360,200,0,360,80,80);
sector(280,280,0,360,120,70);
sector(360,280,0,360,60,75);
sector(15,450,0,360,55,80);
sector(260,460,0,360,60,30);
sector(600,470,0,360,150,30);
sector(15,410,0,360,20,80);
sector(30,20,0,360,40,25);
sector(500,0,0,360,90,50);
sector(600,15,0,360,80,50);
sector(630,230,0,130,50,100);
sector(610,160,0,120,50,120);
sector(610,450,0,110,75,100);
sector(650,350,0,220,60,100);
sector(140,15,0,200,80,30);
sector(200,20,0,360,100,50);
sector(60,150,60,220,150,200);
sector(150,30,0,360,100,100);
sector(5,240,30,330,40,90);
sector(630,240,0,360,70,100);
sector(360,5,0,360,100,30);
sector(630,240,110,300,70,100);
sector(0,280,0,360,80,100);
sector(100,470,360,360,120,60);
pieslice(380,420,200,340,100);
end;
begin
clrscr;
Gd:=VGA;
Gm:=VGAhi;
initgraph(Gd,Gm,'');
if graphresult=grok then
begin
bereg;
setcolor(brown);
setfillstyle(1,brown);
posX:=500;
posY:=250;
fillellipse(posX,posY,1,1);
repeat
ch:=readkey;
case ch of
#72:begin posY:=posY-5; fillellipse(posX,posY,1,1);setcolor(black);
setfillstyle(0,black);fillellipse(posX,posY+5,1,1);setcolor(brown);
setfillstyle(1,brown); end;
#75:begin posX:=posX-5; fillellipse(posX,posY,1,1);setcolor(black);
setfillstyle(0,black);fillellipse(posX+5,posY,1,1); setcolor(brown);
setfillstyle(1,brown); end;
#77:begin posX:=posX+5; fillellipse(posX,posY,1,1);setcolor(black);
setfillstyle(0,black);fillellipse(posX-5,posY,1,1);setcolor(brown);
setfillstyle(1,brown); end;
#80:begin posY:=posY+5; fillellipse(posX,posY,1,1);setcolor(black);
setfillstyle(0,black);fillellipse(posX,posY-5,1,1);setcolor(brown);
setfillstyle(1,brown); end;
#27:halt;
end;{case}
until ch=#27;
closegraph;
end
else
writeln(grapherrormsg(graphresult));
end.
>Как сделать чтоб кораблик при нажатиии клавиши начинал двигаться в направлении нажатой стрелки и не прекращал движение? Сейчас он двигается только, когда стрелка нажата.
Сначала надо полностью продумать систему уравления. Как, например, остановить корабль? В играх от Sierra, например, было принято, что остановка происходит при повторном нажатии на клавишу. Но может оказаться целесообразной и остановка путем нажатия на клавишу противоположного направления. И в том, и в другом случае необходимы переменные, в которых запоминается текущее состояние движения.
>Можно ли сделать движение по диагонали? Сейчас судно движется только в четырех направлениях.
Можно, конечно. При этом даже различными способами. Например, при использовании цифровой клавиатуры либо при одновременном нажатии двух клавиш.
>Как реализовать крушение кораблика при столкновении с берегом? (Видимо, нужно написать функцию, возвращающую значение цвета пикселов вокруг кораблика, и если эти значения равны значению цвету берега - корабль тонет)
Можно и так.
>Как с помощью Pascal реализовать счетчик времени? Ведь цель игры - пройти дистанцию за наименьшее время. Искал в учебниках, а там работа только с временем системы. Как сделать, чтоб игрок вводил свое имя и результаты записывались в текстовый файл?
Правильно. Другого времени и не существует.
В момент старта запоминаешь текущаа состояние времени, а потом вычитаешь его из текущих показаний.
Ввод имени, очевидно, осуществляется процедурой realln, а запись его в файл - writeln.
>Как сделать скорость кораблика независимой от тактовой частоты? Ведь delay зависит, если не ошибаюсь, от этого параметра, значит на разных компьютерах игра с этой процедурой будет иметь разную скорость?
А она зависит? Delay специально сделана так, чтобы не зависела. Но с одной стороны - ты ее не используешь, а с другой - скорость в твоем случае определяется скоростью автоповтора клавиатуры. Чтобы избавиться от этого эффекта, можно использовать:
if keypressed then ch := readkey;
Но в этом случае тебе придется заботиться о скорости другим способом (пока ты вообще об этом не заботишься).
Еще пара замечаний:
- насколько я понял, при нажатии Esc у тебя происходит мгновенный выход из программы в обход конца цикла и восстановления режима.
- целесообразно внутри case выполнять только минимум действий: в данном случае лишь вычисление приращений координат, а всю остальную работу делать в одном месте (чтобы при изменении способа отображения корабля не пришлось менять код в 4-х местах одновременно).
andriano, спасибо за обстоятельный ответ.
Я попробовал сделать движение без постоянного удержания клавиши, и реализовать столкновение с берегом. Насчет системы движения: корабль должен двигаться непрерывно, не останавливаясь, есть возможность только менять направление движения, поэтому переменных для описания состояния движения не вводил. Однако, я совсем запутался даже здесь.
case ch of
#72:repeat
begin
while
(getpixel(posX+1,posY+1)and getpixel(posX-1,posY+1)and
getpixel(posX-1,posY-1)and getpixel(posX+1,posY-1)<>14)do
{проверка условия, не является ли цвет пикселей вокруг корабля цветом берега}
begin posY:=posY-5; fillellipse(posX,posY,1,1);setcolor(black);
setfillstyle(0,black);fillellipse(posX,posY+5,1,1);setcolor(brown);
setfillstyle(1,brown);delay(700) {отрисовка движения}
end;
end
until keypressed=true; {задумывалось как выход из цикла при нажатии клавиши}
{cleardevice; write('Game over. Press Enter, then Esc to exit.');readln;}
{задумывалось как выход из цикла и завершение игры}
repeat
if keypressed then begin
ch := readkey;
case ch of
#72: direction := 1; {переменная, указывающая направление движения}
#75: direction := 2;
#77: direction := 3;
#80: direction := 4;
end; {case ch}
end; {if keypressed}
MoveShip(direction); {процедура, перемещающая корабль}
DrawShip; {процедура, рисующая корабль}
delay(50);
if CheskCollision then begin {функция, проверяющая столкновение с берегом}
for i := 0 to 19 do begin {я думаю, 20 кадров анимации крушения достаточно?}
DrawAnimation(i);
delay(50);
end; {if CheskCollision}
ch := #27; {просто способ принудительно выйти из цикла}
end;
until ch = #27;
(getpixel(posX+1,posY+1)and getpixel(posX-1,posY+1)and getpixel(posX-1,posY-1)and getpixel(posX+1,posY-1)<>14)Здесь ты пытаешься над цветом пикселя совершать логические операции.
(getpixel(posX+1,posY+1) <> 14) and (getpixel(posX-1,posY+1) <> 14) and (getpixel(posX-1,posY-1) <> 14)and (getpixel(posX+1,posY-1)<>14)
andriano, спасибо больщущее!
Благодаря тебе кое-что получилось, теперь уже можно играть. Конечно, пока все очень примитивно - анимация крушения, например, это всего лишь мигание кружка. Правила там не описал пока, поэтому здесь кратко: управляем корабликом - кружок, пока не врежемся в берег. Цель - не врезаться подольше.
program MAPA3M;В аттаче - exe-шник, смотрите. Только у меня exe-шник всего лишь один раз запускается, не знаю почему, а потом пишет код графической ошибки "No error" и выкидывает.
uses crt, graph;
var
Gd,Gm:integer;
posX,posY,i:integer;
ch:char;
dir:integer;
procedure
bereg;
begin
setcolor(yellow);
setfillstyle(7,yellow);
sector(280,200,0,360,100,50);
sector(360,200,0,360,80,80);
sector(280,280,0,360,120,70);
sector(360,280,0,360,60,75);
sector(15,450,0,360,55,80);
sector(260,460,0,360,60,30);
sector(600,470,0,360,150,30);
sector(15,410,0,360,20,80);
sector(30,20,0,360,40,25);
sector(500,0,0,360,90,50);
sector(600,15,0,360,80,50);
sector(630,230,0,130,50,100);
sector(610,160,0,120,50,120);
sector(610,450,0,110,75,100);
sector(650,350,0,220,60,100);
sector(140,15,0,200,80,30);
sector(200,20,0,360,100,50);
sector(60,150,60,220,150,200);
sector(150,30,0,360,100,100);
sector(5,240,30,330,40,90);
sector(630,240,0,360,70,100);
sector(360,5,0,360,100,30);
sector(630,240,110,300,70,100);
sector(0,280,0,360,80,100);
sector(100,470,360,360,120,60);
pieslice(380,420,200,340,100);
end;
procedure
moveship;
begin
if dir=1 then
begin
posY:=posY-5;
fillellipse(posX,posY,2,2);
setcolor(black);
setfillstyle(0,black);
fillellipse(posX,posY+5,2,2);
setcolor(brown);
setfillstyle(1,brown);
end;{if dir=1}
if dir=2 then
begin
posX:=posX-5;
fillellipse(posX,posY,2,2);
setcolor(black);
setfillstyle(0,black);
fillellipse(posX+5,posY,2,2);
setcolor(brown);
setfillstyle(1,brown);
end;{if dir=1}
if dir=3 then
begin
posX:=posX+5;
fillellipse(posX,posY,2,2);
setcolor(black);
setfillstyle(0,black);
fillellipse(posX-5,posY,2,2);
setcolor(brown);
setfillstyle(1,brown);
end;{if dir=1}
if dir=4 then
begin
posY:=posY+5;
fillellipse(posX,posY,2,2);
setcolor(black);
setfillstyle(0,black);
fillellipse(posX,posY-5,2,2);
setcolor(brown);
setfillstyle(1,brown);
end;{if dir=1}
end;{procedure}
procedure drawcollision;
begin
fillellipse(posX,posY,2,2);
delay(5000);
setcolor(black);
setfillstyle(1,black);
fillellipse(posX,posY,2,2);
delay(5000);
setcolor(brown);
setfillstyle(1,brown);
end;
{*******************************main*************************************}
begin
clrscr;
Gd:=VGA;
Gm:=VGAhi;
initgraph(Gd,Gm,'');
if graphresult=grok then
begin
bereg;
setcolor(brown);
setfillstyle(1,brown);
posX:=500;
posY:=250;
fillellipse(posX,posY,2,2);
repeat
if keypressed then
begin
ch:=readkey;
case ch of
#72:dir:=1;
#75:dir:=2;
#77:dir:=3;
#80:dir:=4;
end; {case ch}
end;
moveship;
delay(900);
if (getpixel(posX+5,posY)=14) or (getpixel(posX-5,posY)=14) or
(getpixel(posX,posY+5)=14) or (getpixel(posX,posY-5)=14) then
begin
i:=1;
for i:=1 to 8 do
begin
drawcollision;
end;{for}
ch:=#27;
end;{if..then}
until ch=#27;
closegraph;
writeln('Game over. Press Enter to exit.');
readln;
end
else
writeln(grapherrormsg(graphresult));
end.
По поводу ошибки - ничего сказать не могу, нет у меня ТР/ВР, да и когда был, предпочитал не пользоваться модулем graph, так что тонкостей его использования просто не знаю.
По поводу кода, рекомендую все-таки вызывать из основной программы не 1, а 3 процедуры: RestoreBackground, MoveShip и DrawShip. Просто потому, что они выполняют разную работу.
И еще: ты сначала рисуешь корабль, а потом удаляешь его старое изображение. Это неправильно. Правильно: сначала восстановить фон, затем нарисовать новое изображение.
procedure RestoreBackground;
begin
setcolor(black);
setfillstyle(0,black);
fillellipse(posX,posY,2,2);
end;
procedure MoveShip(direction : integer);
begin
case direction of
1:...
2:...
3:...
4:...
end;
end;
procedure DrawShip;
begin
setcolor(brown);
setfillstyle(1,brown);
fillellipse(posX,posY,2,2);
end;
Да, Delay зависит от производительности ЦП.
Вот модуль, который позволит делать задержку независимо, от ЦП:
Unit Timer;Тут есть 3 процедуры: Start, Stop, Pause
interface
procedure Start (var T:longint);
procedure Stop (var T:longint);
procedure Pause (T:longint; Show:boolean);
Implementation
SystemTimer:longint absolute $0040:$006C;
procedure Start (var T:longint);
begin
T:=SystemTimer;
end;
procedure Stop (var T:longint);
begin
T:=SystemTimer-T;
end;
procedure Pause (T:longint; Show:boolean);
var Xn,Xt:longint;
begin
Xt:=0;
Xn:=SystemTimer;
While ((Xt-Xn)/18.2)*1000 < T do
begin
Xt:=SystemTimer;
If Show then
writeln((xt-xn)/18.2:6:4)
end;
end;
end.
Вообще-то это не очень хороший вариант.
Начиная с IBM PC AT поддерживается 15h прерывание, одной из функций которого как раз и есть формирование временной задержки. Кстати, величина ее задается в микросекундах, но зачем - непонятно, все равно такая точность не выдерживается.
Сейчас уже не 1992 год, компьютеры IBM PC и IBM PC XT свое отслужили и о совместимости с ними вряд ли надо заботиться. С другой стороны, на старших моделях 486 и большинстве Pentium'ов программы, содержащие модуль crt "падали" из-за переполнения при инициализации этого модуля, вызванного как раз вычислением константы для процедуры delay.
Собственно, сегодня практически все компиляторы ТР содержат уже пропатченный модуль crt. Грамотно сделанный патч выглядит так:
procedure delay(Wait:word); assembler; {єбсСαЄ¬б у јЯ}
asm
mov ax,Wait
mov dx,1000
mul dx
mov cx,dx
mov dx,ax
mov ah,$86
int $15
end;
Вопрос в том, как проверить, пропаченый модуль или нет?
Проще описать вот эту процедуру, только назвать ее MyDelay (чтобы не конфликтовали) и использовать ее, чтобы не волноваться
Если на компе с тактовой частотой 200 МГц и выше работает, значит, патченый.
Прошу прощения за долгое отсутствие.
Я поискал по форуму меню, наткнулся на такую версию:
begin
clrscr;
Gd:=VGA;
Gm:=VGAhi;
initgraph(Gd,Gm,'');
if graphresult=grok then
begin
choice:=Menu('Play'#13'Exit');
while (choice=0) do
begin
bereg;
setcolor(brown);
setfillstyle(1,brown);
posX:=500;
posY:=250;
fillellipse(posX,posY,2,2);
repeat
if keypressed then
begin
ch:=readkey;
case ch of
#72:dir:=1;
#75:dir:=2;
#77:dir:=3;
#80:dir:=4;
end; {case ch}
end;
restore_background;
moveship(dir);
draw_ship;
delay(900);
if (getpixel(posX+5,posY)=14) or (getpixel(posX-5,posY)=14) or
(getpixel(posX,posY+5)=14) or (getpixel(posX,posY-5)=14) then
begin
i:=1;
for i:=1 to 8 do
begin
drawcollision;
end;{for}
ch:=#27;
end;{if..then}
until ch=#27;
choice:=Menu('Play'#13'Exit');
dir:=0;
ch:=' ';
end;
closegraph;
halt;
end
else
writeln(grapherrormsg(graphresult));
end.
Программа была мною еще доработана - появилась анимация крушения и анимация поворота. Однако при доработке не удалось сохранить первоначальную стройную структуру, предложенную andriano. Видимо, эта проблема вызвана отсутствием навыка в построении блок-схем. Надеюсь услышать коструктивную критику
program MAPA3M;
uses crt, graph;
var
Gd,Gm:integer;
posX,posY,i,k,n:integer;
ch:char;
dir,ldir,choice:integer;
m:array [1..6] of pointtype;
const z=10;{zaderzgka}
function checkcollision(posX,posY:integer):boolean;
begin
checkcollision:=false;
if (getpixel(posX+8,posY+3)=darkgray) or (getpixel(posX-8,posY-3)=darkgray) or
(getpixel(posX+3,posY+8)=darkgray) or (getpixel(posX-3,posY-8)=darkgray) or
(getpixel(posX+8,posY-3)=darkgray) or (getpixel(posX-8,posY+3)=darkgray) or
(getpixel(posX-3,posY+8)=darkgray) or (getpixel(posX+3,posY-8)=darkgray)
then
checkcollision := true;
end;
function Menu(Params: string): integer;
var
Count: integer;
Strings: array [0 .. 15] of string [127];
i: integer;
Ch: char;
X, Y, H: integer;
begin
Count := 1;
Strings[0] := '';
for i := 1 to Length(Params) do begin
if Params[i] = #13 then begin
Inc(Count);
Strings[Count - 1] := '';
end else begin
Strings[Count - 1] := Strings[Count - 1] + Params[i];
end;
end;
SetTextJustify(CenterText, CenterText);
H := TextHeight('A') + 10;
ClearDevice;
SetColor(WHITE);
for i := 0 to Count - 1 do
OutTextXY(GetMaxX div 2,
GetMaxY div 2 - (Count - 1) * H div 2 - H div 4 + i * H, Strings[i]);
i := 0;
repeat
SetColor(GREEN);
X := TextWidth(Strings[i]) + 10;
Y := TextHeight(Strings[i]) + 10;
Rectangle(GetMaxX div 2 - X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H - Y div 2,
GetMaxX div 2 + X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H + Y div 2);
ch := readkey;
SetColor(BLACK);
X := TextWidth(Strings[i]) + 10;
Y := TextHeight(Strings[i]) + 10;
Rectangle(GetMaxX div 2 - X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H - Y div 2,
GetMaxX div 2 + X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H + Y div 2);
case ch of
#0: case ReadKey of
#72: begin Dec(i);
if i < 0 then
i := Count - 1;
end;
#80: begin
Inc(i);
if i >= Count then
i := 0;
end;
end;
end;
until ch = #13;
Menu := i;
end;
procedure delay(Wait:word); assembler;
asm
mov ax,Wait
mov dx,1000
mul dx
mov cx,dx
mov dx,ax
mov ah,$86
int $15
end;
procedure
bereg;
begin
cleardevice;
setcolor(darkgray);
setfillstyle(2,darkgray);
{sector(280,200,0,360,100,50);}
sector(360,200,0,360,80,80);
sector(280,280,0,360,120,70);
sector(360,280,0,360,60,75);
sector(15,450,0,360,55,80);
sector(260,460,0,360,60,30);
sector(600,470,0,360,150,30);
sector(15,410,0,360,20,80);
sector(30,20,0,360,40,25);
sector(500,0,0,360,90,50);
sector(600,15,0,360,80,50);
sector(630,230,0,130,50,100);
sector(610,160,0,120,50,120);
sector(610,450,0,110,75,100);
sector(650,350,0,220,60,100);
sector(140,15,0,200,80,30);
sector(200,20,0,360,100,50);
sector(60,150,60,220,150,200);
sector(150,30,0,360,100,100);
sector(5,240,30,330,40,90);
sector(630,240,0,360,70,100);
sector(360,5,0,360,100,30);
sector(630,240,110,300,70,100);
sector(0,280,0,360,80,100);
sector(100,470,360,360,120,60);
pieslice(380,420,200,340,100);
end;
procedure
restore_background(dir:integer);
begin
if dir=0 then
begin
setcolor(brown);
setfillstyle(1,brown);
fillellipse(posX,posY,8,3);
end;
if (dir=2) or (dir=3) then
begin
setcolor(blue);
setfillstyle(0,blue);
fillellipse(posX,posY,14,4);
end;
if (dir=1) or (dir=4) then
begin
setcolor(blue);
setfillstyle(1,blue);
fillellipse(posX,posY,4,14);
end
end;
procedure
moveship(dir:integer);
begin
case dir of
1: posY:=posY-5;
2: posX:=posX-5;
3: posX:=posX+5;
4: posY:=posY+5;
end;{case}
end;{procedure}
procedure drawcollision(dir:integer);
var a,z:integer;
begin
if (dir=1) then
begin
setcolor(blue);
setfillstyle(0,1);
fillellipse(posX,posY+13,4,4);
for z:=0 to 8 do
begin
for a:=0 to 6 do
begin
putpixel(posX+3-a,posY+8-z,blue);
delay(z*500);
end;
end;
end;
if (dir=2) then
begin
setcolor(blue);
setfillstyle(0,1);
fillellipse(posX+13,posY,4,4);
for z:=0 to 8 do
begin
for a:=0 to 6 do
begin
putpixel(posX+8-z,posY+3-a,blue);
delay(z*500);
end;
end;
end;
if (dir=3) then
begin
setcolor(blue);
setfillstyle(0,0);
fillellipse(posX-13,posY,4,4);
for z:=0 to 8 do
begin
for a:=0 to 6 do
begin
putpixel(posX-8+z,posY-3+a,blue);
delay(z*500);
end;
end;
end;
if (dir=4) then
begin
setcolor(blue);
setfillstyle(0,0);
fillellipse(posX,posY-13,4,4);
for z:=0 to 8 do
begin
for a:=0 to 6 do
begin
putpixel(posX-3+a,posY-8+z,blue);
delay(z*500);
end;
end;
end;
end;
procedure draw_ship(dir:integer);
begin
setcolor(brown);
setfillstyle(1,brown);
if (dir=1) then
begin
fillellipse(posX,posY,3,8);
setfillstyle(11,lightgray);
randomize;
setcolor(blue);
fillellipse(posX,posY+10+random(2),3,2);
end;
if (dir=2) then
begin
fillellipse(posX,posY,8,3);
setfillstyle(11,lightgray);
randomize;
setcolor(blue);
fillellipse(posX+10+random(2),posY,2,3);
end;
if (dir=3) then
begin
fillellipse(posX,posY,8,3);
setfillstyle(11,lightgray);
randomize;
setcolor(blue);
fillellipse(posX-10+random(2),posY,2,3);
end;
if (dir=4) then
begin
fillellipse(posX,posY,3,8);
setfillstyle(11,lightgray);
randomize;
setcolor(blue);
fillellipse(posX,posY-10+random(2),3,2);
end;
end;
procedure changedirhv;
begin
for k := 0 to 6 do with m[k] do
begin
x:=trunc(posX+((8-n)*cos(k*1.05)));
y:=trunc(posY-((3+n)*sin(k*1.05)));
end;
setcolor(blue);
setfillstyle(0,blue);
fillellipse(posX,posY,12,12);
setcolor(brown);
setfillstyle(1,brown);
fillpoly(6,m);
delay(z*1900);
end;
procedure changedirvh;
begin
setcolor(brown);
setfillstyle(1,brown);
for k := 0 to 6 do with m[k] do
begin
x:=trunc(posX+((3+n)*cos(k*1.05)));
y:=trunc(posY-((8-n)*sin(k*1.05)));
end;
setcolor(blue);
setfillstyle(0,blue);
fillellipse(posX,posY,12,12);
setcolor(brown);
setfillstyle(1,brown);
fillpoly(6,m);
delay(z*1900);
end;
procedure changedir(dir,ldir:integer);
begin
for n:=0 to 5 do
begin
if ((ldir=2)or(ldir=3)or(ldir=0))and((dir=1)or(dir=4)) then
begin
changedirhv;
moveship(dir);
end;
if ((ldir=1)or(ldir=4))and((dir=2)or(dir=3)) then
begin
changedirvh;
moveship(dir);
end;
end;
if ((ldir=2)and(dir=3))or((ldir=3)and(dir=2)) or
((ldir=1)and(dir=4))or((ldir=4)and(dir=1)) then
delay(z*1900);
end;
{*******************************main*************************************}
begin
clrscr;
Gd:=VGA;
Gm:=VGAhi;
initgraph(Gd,Gm,'');
if graphresult=grok then
begin
choice:=Menu('Play'#13'Exit');
while (choice=0) do
begin
setbkcolor(blue);
cleardevice;
bereg;
posX:=500;
posY:=250;
{draw_ship(2);}
repeat
if keypressed then
begin
ch:=readkey;
case ch of
#72:begin ldir:=dir; dir:=1; changedir(dir,ldir); end;
#75:begin ldir:=dir; dir:=2; changedir(dir,ldir); end;
#77:begin ldir:=dir; dir:=3; changedir(dir,ldir); end;
#80:begin ldir:=dir; dir:=4; changedir(dir,ldir); end;
end; {case ch}
end;
restore_background(dir);
moveship(dir);
draw_ship(dir);
delay(z*1000);
if checkcollision(posX,posY)=true then
begin
drawcollision(dir);
ch:=#27;
setbkcolor(black);
cleardevice;
end;{if..then}
until ch=#27;
choice:=Menu('Play'#13'Exit');
dir:=0;
ch:=' ';
end;
closegraph;
halt;
end
else
writeln(grapherrormsg(graphresult));
end.
Предыдущее сообщение мое.
Поставь 2 задержки подряд...
1. Если планируется отрабатывать несколько различных состояний, то основа главного игрового цикла остается, занчительная часть внутренности (кроме опроса клавиатуры, задержки и т.п.) выносится в отдельную процедуру и такие процедуры пишутся для каждого из состояний. Вводится новая переменная - номер текущего состояния, по которой (case) выбирается нужная процедура внутри цикла. Там же записываются условия перехода из одного состояния в другое (конечный автомат).
2. Почему проблемы с delay, честно говоря, не понимаю. В том виде, как она записана, она позволяет делать задержку до 65.5 сек, чего, думаю, более, чем достаточно. Если этого по каим-то причинам мало, то можно сделать так:
procedure delay(Wait:longint);
var l : longint;
begin
l := wait*1000;
asm
mov cx,word ptr [l+2]
mov dx,word ptr [l]
mov ah,$86
int $15
end;
end;
Вот что получилось - корабль нарисован из круга, прямоугольника и треугольника. Анимация реализована максимально просто - экран каждый раз очищается полностью. Константы s, v, c позволяют менять соответственно размер, скорость и цвет кораблика.
Код:
uses crt,graph;
var
Gd,Gm:integer;
x,y,dx,dy,ds,alpha:real;
ch:char;
const
s=10; {size}
v=3; {speed}
c=white; {colour}
procedure kvad(x,y:integer;a:real);
var s1,s2,s3:real;
begin
s1:=s/2;
s2:=s*(1+sqrt(3))/2;
s3:=s2/3;
line(round(x-s1*cos(a)-s1*sin(a)),round(y+s1*sin(a)-s1*cos(a))
,round(x-sin(a)*s2),round(y-cos(a)*s2));
line(round(x-sin(a)*s2),round(y-cos(a)*s2),
round(x+s1*cos(a)-s1*sin(a)),round(y-s1*sin(a)-s1*cos(a)));
line(round(x-s1*cos(a)+s1*sin(a)),round(y+s1*sin(a)+s1*cos(a)),
round(x-s1*cos(a)-s1*sin(a)),round(y+s1*sin(a)-s1*cos(a)));
line(round(x+s1*cos(a)+s1*sin(a)),round(y-s1*sin(a)+s1*cos(a)),
round(x+s1*cos(a)-s1*sin(a)),round(y-s1*sin(a)-s1*cos(a)));
circle(round(x+s1*sin(a)),round(y+s1*cos(a)),
round(s1));
floodfill(round(x+s1*sin(a)),round(y+s1*cos(a)),c);
floodfill(round(x-sin(a)*s3),round(y-cos(a)*s3),c);
end;
{********main*******}
begin
ClrScr;
Gd:=detect;
InitGraph(Gd,Gm,'');
if GraphResult = GrOk then
begin
x:=GetMaxX div 2;
y:=GetMaxY div 2;
ds:=1;
alpha:=0;
SetBkColor(Blue);
ClearDevice;
repeat
if KeyPressed then
begin
ch:=readkey;
case ch of
#77: alpha:=alpha-0.1;
#75: alpha:=alpha+0.1;
#27: begin CloseGraph; halt; end;
end; {case}
end;
{SetColor(Blue);
SetFillStyle(1,blue);
kvad(round(x),round(y),alpha-pi/2);}
dx:=ds*cos(alpha); dy:=ds*sin(alpha);
x:=x+dx;
y:=y-dy;
ClearDevice;
SetColor©;
SetFillStyle(1,c);
kvad(round(x),round(y),alpha-pi/2);
Delay(round(10/v)*200);
until ch = #27;
end
else WriteLn(GraphErrorMsg(GraphResult));
end.