Задача: создать игру в жанре арканоид (классический). Довольно простая реализация арканоида. Написана на паскале, кроме того код совершенно не оптимизирован, поэтому, если у вас появится желание написать что-то подобное, не советую использовать данную архитектуру (архитектурой то и назвать это сложно). Состоит игра из 2 глобальных состояний: Основной задачей было в как можно большей степени описать полёт шарика. В результате шарик летает по своему вектору скорости, с каждым новым кадром к его текущим координатам приплюсовывается скорость (х, у). Проводится анализ его нового положения и производятся соответствующие корректировки. В игре принимают участие 2 игрока. Игра заканчивается при достижении одним из игроков победы в 10 раундах. Раунд заканчивается, когда шарик заходит за границу движения платформы одного из игроков. Управление: Ещё раз акцентирую ваше внимание на том, что в изучении архитектуры этой программы нет никакого смысла - эта игра скорее подпадает под категорию "Prove of concept" - что на паскале тоже можно писать довольно неплохие игры. P.S. Постарался и закомментил весь код на английском, поэтому заранее извиняюсь за возможные грамматические ошибки. { ARCANOID } { pretty simple game with a title and game states } uses crt,graph,keyboard,windos; { keyboard - library (just a file), that gives more advantages } { to work with keyboard. Like pressing multi keys at once } { I'm using it to make possible two-player game and to remove } { the standart pausing affect (delay when key is pressed down) } { This library written not by me. You can find more info if } { open that file } { This program was written when I wasn't very skilled in } { object oriented programming, so it's a little indian-style } { (hmm, a much indian-style, but I'll try to explain what I could remember) } { So, don't try to write program like this. It's just a prove } { of concept - that games can be written using pascal } label 1; { yea, I was using labels. LMAO } const PathToDriver = 'bgi\'; { this is exactly what you are thinking} ShipSpeed = 4; { name says for itself } Ballaks = 0.1; { after each "pong" ball accelerating } var score1,score2:byte; size:word; p1,p2,p3,p4,p5,p10,p11,p20,p21:pointer; BallSpeed:real; { current speed of ball } p,q:real; { Vektor of ball moving } Long:integer; { Length of the ship } Xprev,Yprev:real; { previos frame's ball position } ShipPos,ShipPrev,ShipPos2,ShipPrev2:real; { positions of platforms } X,Y:real; { Current Position of the Ball } tg:real; { tg30 } { Main drawing a title-screen } procedure Main; const kx1 = 100; ky1 = 300; var ax,ay,bx,by,cx:real; i:integer; size:word; p1,p2:pointer; x1,y1:integer; x2,y2:integer; xS,yS:integer; x,xx,xxx,xxxxx,d1,d2,d3,d5:real; x0,xx1,xxx1,xxxxx1,d11,d21,d31,d51:real; color:byte; { Form for a buttons (that show the controls left, right, A, D } procedure button(kx,ky:integer; ch:char); begin setcolor(2); arc(kx-6,ky-6,90,180,4); arc(kx+6,ky-6,0,90,4); arc(kx-6,ky+6,180,270,4); arc(kx+6,ky+6,270,360,4); settextstyle(3,0,1); outtextxy(kx-4,ky-13,ch); end; { I don't know why I named it "pixel", but this thing is used } { to draw a points flying by the ellipse traectory } procedure pixel(color:byte; var x,d:real); var j:integer; begin setcolor(color); for j:=1 to 20 do begin if d>0 then i:=-1 else i:=1; x:=x+d; circle(433+round(x),329+i*round(sqrt(abs(1600*(1-sqr(x)/10000)))),1); if x>100 then d:=-d; if x<-100 then d:=-d; end; end; begin setcolor(3); arc(200,200,270,340,30); line(200,230,140,230); line(140,230,140,211); line(140,211,227,211); line(150,211,150,196); line(150,196,170,196); line(170,196,180,182); line(180,182,198,182); line(198,182,198,211); setcolor(1); circle(200,220,5); circle(180,220,5); circle(160,220,5); rectangle(181,188,185,192); rectangle(189,188,193,192); line(190,181,190,172); line(194,181,194,176); { Preparing the image-buffer } size:= imagesize(140,172,228,230); getmem(p1,size); getimage(140,172,228,230,p1^); putimage(140,172,p1^,XorPut); randomize; x2:=300; y2:=103; size:= imagesize(90,100,310,150); getmem(p2,size); { Drawing controls for players } settextstyle(2,0,5); setcolor(12); outtextxy(550,10,'Player 2'); button(560,40,'A'); button(599,40,'D'); settextstyle(2,0,5); setcolor(9); outtextxy(30,420,'Player 1'); button(40,450,' '); button(78,450,' '); line(40-4,450,40+4,450); line(40-4,450,40-1,450-3); line(40-4,450,40-1,450+3); line(78-4,450,78+4,450); line(78+4,450,78+1,450-3); line(78+4,450,78+1,450+3); setcolor(0); setfillstyle(0,14); fillellipse(433,329,99,39); { Drawing a pseudo-3D "SPACER" } setcolor(1); settextstyle(4,0,5); outtextxy(351,301,'SPACER'); outtextxy(352,301,'SPACER'); setcolor(9); outtextxy(350,300,'SPACER'); { Same thing "cray0000 present" } setcolor(4); settextstyle(2,0,7); outtextxy(108,112,'cray0000 present'); outtextxy(109,112,'cray0000 present'); setcolor(14); outtextxy(107,111,'cray0000 present'); { Now I'm going to draw the lightning. } { It's very noob-style coded with lots of code repeating } { and variables. } setfillstyle(1,0); color:=14; d1:=0.1; d2:=0.1; d3:=0.1; d5:=0.1; d11:=-0.1; d21:=-0.1; d31:=-0.1; d51:=-0.1; x:=-80; xx:=-83; xxx:=-86; xxxxx:=-96; x0:=80; xx1:=83; xxx1:=86; xxxxx1:=96; repeat bar(395,1,500,260); { clearing drawing area } bar(395,150,210,260); { } bar(210,260,310,400); { } bar(260,400,360,480); { } { - - - - - - - - - - - } setcolor(15); cx:=400; by:=1; bx:=395+random(15); { first lightning } { Points going with random distance from starting point to finishing } { (ax,ay) and (bx,by) - previos and current positions. } { By the way lightnings are doubled, but I was too stupid to write } { at least a function to automize that drawing process } while cx<480 do begin ay:=by; ax:=bx; cx:=cx+4; bx:=cx+random(20); by:=3*cx-1195+random(10); line(round(ax),round(ay),round(bx),round(by)); end; {second lightning } while cx>220 do begin ay:=by; ax:=bx; cx:=cx-10; bx:=cx-5+random(10); by:=cx/6+155+random(20); line(round(ax),round(ay),round(bx),round(by)); end; { third lightning } while by<480 do begin ay:=by; ax:=bx; cx:=cx+4; bx:=cx+random(20); by:=3*cx-460+random(10); line(round(ax),round(ay),round(bx),round(by)); end; {while (port[$3da] and 8) = 0 do;} { and again lightnings. I should better make a procedure, yeah. } setcolor(14); cx:=400; by:=1; bx:=395+random(15); while cx<480 do begin ay:=by; ax:=bx; cx:=cx+4; bx:=cx+random(20); by:=3*cx-1195+random(10); line(round(ax),round(ay),round(bx),round(by)); end; while cx>220 do begin ay:=by; ax:=bx; cx:=cx-10; bx:=cx-5+random(10); by:=cx/6+155+random(20); line(round(ax),round(ay),round(bx),round(by)); end; while by<480 do begin ay:=by; ax:=bx; cx:=cx+4; bx:=cx+random(20); by:=3*cx-460+random(10); line(round(ax),round(ay),round(bx),round(by)); end; {while (port[$3da] and 8) = 0 do;} bar(90,100,310,110); bar(90,111,100,139); bar(90,140,310,150); bar(300,111,310,139); setcolor(15); xS:=300+random(10); yS:=100+random(10); x2:=xS; y2:=yS; while x2>100 do begin x1:=x2; y1:=y2; x2:=x2-(5+random(5)); y2:=100+random(10); line(x1,y1,x2,y2); end; while y2<140 do begin x1:=x2; y1:=y2; x2:=90+random(10); y2:=y2+(5+random(5)); line(x1,y1,x2,y2); end; while x2<300 do begin x1:=x2; y1:=y2; x2:=x2+(5+random(5)); y2:=140+random(10); line(x1,y1,x2,y2); end; while y2>110 do begin x1:=x2; y1:=y2; x2:=300+random(10); y2:=y2-(5+random(5)); if y2<=110 then begin x2:=xS; y2:=yS; end; line(x1,y1,x2,y2); end; {while (port[$3da] and 8) = 0 do;} setcolor(14); xS:=300+random(10); yS:=100+random(10); x2:=xS; y2:=yS; while x2>100 do begin x1:=x2; y1:=y2; x2:=x2-(5+random(5)); y2:=100+random(10); line(x1,y1,x2,y2); end; while y2<140 do begin x1:=x2; y1:=y2; x2:=90+random(10); y2:=y2+(5+random(5)); line(x1,y1,x2,y2); end; while x2<300 do begin x1:=x2; y1:=y2; x2:=x2+(5+random(5)); y2:=140+random(10); line(x1,y1,x2,y2); end; while y2>110 do begin x1:=x2; y1:=y2; x2:=300+random(10); y2:=y2-(5+random(5)); if y2<=110 then begin x2:=xS; y2:=yS; end; line(x1,y1,x2,y2); end; { Finally, the end of lightnings-stuff } {while (port[$3da] and 8) = 0 do;} { Drawing a eclipse-flying points } setrgbpalette(7,250,0,0); pixel(0,xxxxx,d5); pixel(7,xxx,d3); pixel(12,xx,d2); pixel(14,x,d1); pixel(0,xxxxx1,d51); pixel(7,xxx1,d31); pixel(12,xx1,d21); pixel(14,x0,d11); { waiting for V-sync. Removing the annoying screen-flashing } while (port[$3da] and 8) = 0 do; until keypressed; end; { Initializing graphics } procedure InitGrapho; var a,b:integer; begin a:=detect; InitGraph(a,b,PathToDriver); end; { Drawing the game units } procedure DrawBall; begin putimage(round(XPrev)-3,round(YPrev)-3,p2^,NormalPut); getimage(round(x-3),round(y-3),round(x+3),round(y+3),p2^); putimage(round(x-3),round(y-3),p1^,NormalPut); end; procedure DrawShip; begin putimage(round(ShipPrev)-4,getmaxy-10,p4^,NormalPut); getimage(round(ShipPos)-4,GetmaxY-10,round(ShipPos)+Long+4,GetMaxY-2,p4^); putimage(round(ShipPos)-4,GetMaxY-10,p3^,NormalPut); end; procedure DrawShip2; begin putimage(round(ShipPrev2)-4,3,p11^,NormalPut); getimage(round(ShipPos2)-4,3,round(ShipPos2)+Long+4,11,p11^); putimage(round(ShipPos2)-4,3,p10^,NormalPut); end; { updating the score of the game and drawing it } { Called when player have losed the round } Procedure Score; begin x:=getmaxx/2; y:=getmaxy-14; BallSpeed:=3; { standart ball's speed at the start of each round } { Instead of constant we can place a variable and } { for example } p:=p/q; { } q:=q/abs(q)*ballspeed; p:=p*q; shipprev:=shippos; shipprev2:=shippos2; shippos:=(getmaxx-long)/2; { reset ship positions } shippos2:=(getmaxx-long)/2; DrawShip; DrawShip2; DrawBall; XPrev:=x; YPrev:=y; putimage(20,85,p20^,NormalPut); putimage(20,355,p21^,NormalPut); settextstyle(4,0,5); setcolor(4); outtextxy(21,137-15-TextHeight(chr(48+score2)),chr(48+score2)); outtextxy(21,136-15-TextHeight(chr(48+score2)),chr(48+score2)); setcolor(12); outtextxy(20,135-15-TextHeight(chr(48+score2)),chr(48+score2)); setcolor(1); outtextxy(21,302+40+15,chr(48+score1)); outtextxy(21,301+40+15,chr(48+score1)); setcolor(9); outtextxy(20,300+40+15,chr(48+score1)); end; { The main "mechanics" of the game (if one can say so) } { Movement model of the flying ball } procedure BallStep; label 1; begin Xprev:=x; Yprev:=y; 1: x:=x+p; y:=y+q; if (x>getmaxx-4) then begin y:=q*(getmaxx-4-x)/p+y; x:=getmaxx-4; p:=-p; goto 1; end; if (x<5) then begin y:=q*(5-x)/p+y; x:=5; p:=-p; goto 1; end; { if ball goes to the lower-ship's y-position then we checking } { if it's hits the ship or not. Same with the upper-ship } { Ball is flying by the vector of speed - (x,y) } { There is also a Left and Right side-vectors. } { They have been used in situations when one of the ships was moving at } { the time it hit the ball. So that the ball's traectory needs the proper } { correction. Ball's vector of speed just having been sumed with one of the } { side-vectors. } if y>getmaxy-14 then begin x:=p*(getmaxy-14-y)/q+x; y:=getmaxy-14; if ((x>=shippos-7) and (x<=Shippos-1) and (p>0)) or ((x>=Shippos+Long+1) and (x<=ShipPos+Long+7) and (p<0)) then p:=-p; if (x<ShipPos-7) or (x>ShipPos+Long+7) then begin score2:=score2+1; if score2>=10 then begin settextstyle(2,0,7); setcolor(12); outtextxy(240,230,'RED'); setcolor(7); outtextxy(240+textwidth('RED '),230+TextHeight('RED')-TextHeight('player wins!'),'player wins!'); while not scandata[1] do; Halt; end; Score; while not scandata[57] do begin if scandata[1]=true then halt; end; Exit; end; q:=-q/abs(q)*ballspeed; if ScanData[$4D] and (ShipPos<getmaxx-6-Long) then p:=(p+BallSpeed*tg)/(2.5+1/(1+random(10))) else if ScanData[$4B] and (ShipPos>7) then p:=(p-BallSpeed*tg)/(2.5+1/(1+random(10))); if ballspeed<=5 then ballspeed:=ballspeed+ballaks; goto 1; end; if (y<15) then begin x:=p*(15-y)/q+x; y:=15; if ((x>=shippos2-7) and (x<=Shippos2-1) and (p>0)) or ((x>=Shippos2+Long+1) and (x<=ShipPos2+Long+7) and (p<0)) then p:=-p; if (x<ShipPos2-7) or (x>ShipPos2+Long+7) then begin score1:=score1+1; if score1>=10 then begin settextstyle(2,0,7); setcolor(9); outtextxy(240,230,'BLUE'); setcolor(7); outtextxy(240+textwidth('BLUE '),230+TextHeight('BLUE')-TextHeight('player wins!'),'player wins!'); while not scandata[1] do; Halt; end; Score; while not scandata[57] do begin if scandata[1]=true then halt; end; Exit; end; q:=-q/abs(q)*ballspeed; if (ScanData[32]) and (ShipPos2<getmaxx-6-Long) then p:=(p+BallSpeed*tg)/(2.5+1/(1+random(10))) else if (ScanData[30]) and (ShipPos2>7) then p:=(p-BallSpeed*tg)/(2.5+1/(1+random(10))); if ballspeed<=5 then ballspeed:=ballspeed+ballaks; goto 1; end; end; { Main body of the program } begin { Initializing graphics and keyboard } InitGrapho; cleardevice; restorekeyboard; setbkcolor(0); main; cleardevice; randomize; setrgbpalette(7,100,100,100); { setting the constants and initializing the variables } BallSpeed:=3; score1:=0; score2:=0; tg:=sin(pi/6)/cos(pi/6); long:=51; x:=getmaxx/2; y:=getmaxy-14; XPrev:=x; YPrev:=y; shippos:=(getmaxx-long)/2; shippos2:=(getmaxx-long)/2; q:=-BallSpeed; p:=tg*BallSpeed; ShipPrev:=ShipPos; ShipPrev2:=ShipPos2; setcolor(2); circle(100,100,3); setfillstyle(1,2); floodfill(100,100,2); putpixel(99,98,10); putpixel(98,99,10); putpixel(98,100,10); size:= imagesize(97,97,103,103); getmem(p1,size); getimage(97,97,103,103,p1^); putimage(97,97,p1^,XorPut); size:= imagesize(97,97,103,103); getmem(p2,size); getimage(97,97,103,103,p2^); putimage(97,97,p2^,XorPut); { painting and remembering the blue player ship model } setcolor(1); arc(320,230,90,270,4); arc(320+long,230,270,90,4); line(320,226,320+long,226); line(320,234,320+long,234); setfillstyle(1,1); floodfill(330,230,1); putpixel(318,228,9); putpixel(318,229,9); putpixel(317,229,9); putpixel(317,230,9); putpixel(317,231,9); putpixel(319,228,9); setcolor(9); line(319,227,320+long,227); size:=imagesize(316,226,320+long+4,234); getmem(p3,size); getimage(316,226,320+long+4,234,p3^); putimage(316,226,p3^,XorPut); size:= imagesize(316,226,320+long+4,234); getmem(p4,size); getimage(316,226,320+long+4,234,p4^); putimage(316,226,p4^,XorPut); { red player } setcolor(4); arc(320,230,90,270,4); arc(320+long,230,270,90,4); line(320,226,320+long,226); line(320,234,320+long,234); setfillstyle(1,4); floodfill(330,230,4); putpixel(318,228,12); putpixel(318,229,12); putpixel(317,229,12); putpixel(317,230,12); putpixel(317,231,12); putpixel(319,228,12); setcolor(12); line(319,227,320+long,227); size:=imagesize(316,226,320+long+4,234); getmem(p10,size); getimage(316,226,320+long+4,234,p10^); putimage(316,226,p10^,XorPut); size:= imagesize(316,226,320+long+4,234); getmem(p11,size); getimage(316,226,320+long+4,234,p11^); putimage(316,226,p11^,XorPut); { BackGround } setcolor(15); for size:=1 to 1000 do putpixel(random(640)+1,random(480)+1,15); setcolor(8); setlinestyle(3,2,2); { line(1,1,getmaxx,1); line(1,1,1,getmaxy); line(getmaxx,getmaxy,1,getmaxy); line(getmaxx,getmaxy,getmaxx,1); } { Score, that draws as a background } size:= imagesize(20,85,65,130); getmem(p20,size); getimage(20,85,65,130,p20^); size:= imagesize(20,355,65,400); getmem(p21,size); getimage(20,315,65,360,p21^); { ---------- } settextstyle(4,0,5); setcolor(6); outtextxy(20+1,135+2,'S'); outtextxy(20+1,170+2,'P'); outtextxy(20+1,205+2,'A'); outtextxy(20+1,240+2,'C'); outtextxy(20+1,275+2,'E'); outtextxy(20+1,300+2,'R'); outtextxy(20+1,135+1,'S'); outtextxy(20+1,170+1,'P'); outtextxy(20+1,205+1,'A'); outtextxy(20+1,240+1,'C'); outtextxy(20+1,275+1,'E'); outtextxy(20+1,300+1,'R'); { 3D-like font. Just drawing it 3 times in right-down position from } { the original :) } setcolor(14); outtextxy(20,135,'S'); outtextxy(20,170,'P'); outtextxy(20,205,'A'); outtextxy(20,240,'C'); outtextxy(20,275,'E'); outtextxy(20,300,'R'); DrawShip; DrawShip2; DrawBall; score; tg:=sin(pi/3)/cos(pi/3); InitKeyboard; { initializing the custom keyboard library } { so that we can press and detect multiple keys at once} { waiting for space key at the start of each round } while not scandata[57] do if scandata[1]=true then halt; { gameloop, do while not pressed Esc } repeat while (port[$3da] and 8) = 0 do; { waiting for V-sync again } { right-arrow key pressed } if (ScanData[32]) and (ShipPos2<=getmaxx-6-Long) then begin ShipPrev2:=ShipPos2; ShipPos2:=ShipPos2+ShipSpeed; if ShipPos2>getmaxx-6-Long then ShipPos2:=getmaxx-6-Long; DrawShip2; end else { left-arrow key pressed } if (ScanData[30]) and (ShipPos2>=7) then begin ShipPrev2:=ShipPos2; ShipPos2:=ShipPos2-ShipSpeed; if ShipPos2<7 then ShipPos2:=7; DrawShip2; end; { D key pressed } if (ScanData[$4D]) and (ShipPos<=getmaxx-6-Long) then begin ShipPrev:=ShipPos; ShipPos:=ShipPos+ShipSpeed; if ShipPos>getmaxx-6-Long then ShipPos:=getmaxx-6-Long; DrawShip; end else { A key pressed } if (ScanData[$4B]) and (ShipPos>=7) then begin ShipPrev:=ShipPos; ShipPos:=ShipPos-ShipSpeed; if ShipPos<7 then ShipPos:=7; DrawShip; end; BallStep; DrawBall; until ScanData[1]; end.
|
|||||||