Привета! Задача формулировалась преподом довольно размыто, поэтому может присутствовать некоторая вольность в выполнении, что не может не радовать. Смысл в том, чтоб написать на 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.
Тут нарисованы берега "лагуны" с островом посередине, вид сверху. Кораблик обозначен коричневой точкой и управляется с клавиатуры, это пока все =/ Как видите, нету навыка работы с процедурами, пишется сложно =/ Что конкретно неясно как реализовать: Как сделать чтоб кораблик при нажатиии клавиши начинал двигаться в направлении нажатой стрелки и не прекращал движение? Сейчас он двигается только, когда стрелка нажата. Можно ли сделать движение по диагонали? Сейчас судно движется только в четырех направлениях. Как реализовать крушение кораблика при столкновении с берегом? (Видимо, нужно написать функцию, возвращающую значение цвета пикселов вокруг кораблика, и если эти значения равны значению цвету берега - корабль тонет) Как с помощью Pascal реализовать счетчик времени? Ведь цель игры - пройти дистанцию за наименьшее время. Искал в учебниках, а там работа только с временем системы. Как сделать, чтоб игрок вводил свое имя и результаты записывались в текстовый файл? Как сделать скорость кораблика независимой от тактовой частоты? Ведь delay зависит, если не ошибаюсь, от этого параметра, значит на разных компьютерах игра с этой процедурой будет иметь разную скорость?
Программа была мною еще доработана - появилась анимация крушения и анимация поворота. Однако при доработке не удалось сохранить первоначальную стройную структуру, предложенную 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;
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.
Как видно, я вставил ассемблерную вставку для того, чтобы программа работала с одинаковой задержкой на разных машинах, но корабль стал плавать слишком быстро, а при попытке увеличить параметр Delay выдается ошибка "Constant out of range", т. е. эта вставка не подходит, помогите пожалуйста сделать лучше. Еще возник вопрос: как осуществить движение корабля под разными углами, чтоб он при нажатии клавиши постепенно менял направление движения? С помощью FillEllipse нарисовать такой корабль не получится, видимо, нужно делать с помощью FillPoly, желательно с большим каоличеством вершин. Но главное - неясно, как задать перемещение, т. е. смену координат.