W tym artykule wykonamy prowizorkę gry plaformowej opartej na warstwach. Aby go zrozumieć musisz zapoznać się z podstawowymi informacjami na temat DelphiX. Znajdziesz je w poprzednich artykułach tego działu.
1. Na początku wstawmy na formę odpowiednie komponenty :
Komponent – Proponowana nazwa
DXSpriteEngine – Engine
DXTimer – DXTimer1 (Interval 0)
DXDraw – DXDraw1 (align alClient)
DXImageList – Grafika
DXInput – DXInput
MediaPlayer – Muza
Gra będzie składać się z trzech warstw :
tło gry
plansza
elementy po których się poruszamy.
Teraz zadeklarujmy nasze zmienne oraz obiekty :
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 |
var pusty ,numer ,start : Byte; gracz, gracz_a : TSprite; type TGracz = class(TImageSprite) // postać protected procedure DoMove(MoveCount: Integer); override; procedure spadanie; end; TGracz_a = class(TImageSprite) // nasza postać ukryta protected procedure DoCollision(Sprite: TSprite; var Done: Boolean); override; end; TTlo = class(TBackgroundSprite) // tło gry end; TWarstwa1 = class(TImageSprite) // warstwa po której się poruszamy end; TWarstwa2 = class(TImageSprite) // warstwa z grafiką gry end; Powyższy kod umieszczamy po tekscie implementation {$R *.dfm} |
Utwórzmy procedurę, która będzie tworzyła wszystkie obiekty wykorzystane w grze :
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
procedure TForm1.Start; begin start:=1; with TTlo.Create(Engine.Engine) do begin SetMapSize(1, 1); Z:=-2; Image := Grafika.Items.Find('tlo'); Tile := true; end; with TWarstwa2.Create(Engine.Engine) do begin Image := Grafika.Items.Find('warstwa2'); Width := Image.Width; Height := Image.Height; PixelCheck:=true; Z:=-1; end; with TWarstwa1.Create(Engine.Engine) do begin Image := Grafika.Items.Find('warstwa1'); Width := Image.Width; Height := Image.Height; PixelCheck:=true; end; Gracz:=TGracz.Create(Engine.Engine); with TGracz(Gracz) do begin Image := Grafika.Items.Find('srodek'); Y := 30; X := 10; Z := 2; Width := Image.Width; Height := Image.Height; PixelCheck:=true; AnimPos:=0; AnimCount:=image.PatternCount; AnimLooped:=true; end; Gracz_a:=TGracz_a.Create(Engine.Engine); with TGracz_a(Gracz_a) do begin Image := Grafika.Items.Find('srodek'); Y := 30; X := 10; Z := 2; Width := Image.Width; Height := Image.Height; PixelCheck:=true; AnimPos:=0; AnimCount:=image.PatternCount; AnimLooped:=true; Visible:=false; end; |
Teraz przejdźmy do OnTmier komponentu DXTimer1 :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
if ((gracz.x > 500)and(engine.engine.x > -550)) or ((gracz.x > 1100)and(engine.engine.x > -1150)) or ((gracz.x > 1700)and(engine.engine.x > -1750)) then Engine.Engine.X := Engine.Engine.X - 50; if ((gracz.x>2300)and(engine.engine.x>-2310)) then Engine.Engine.X := Engine.Engine.X-10; |
Powyższy kod odpowiedzialny jest za przesuwanie planszy, jeżeli gracz dojdzie do brzegu ekranu.
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 |
DXInput.Update; Engine.Engine.Collision; Engine.Move(LagCount); Engine.Draw; //KONIEC GRY if unit1.start=2 then begin grafika.Items.Find('koniec').Draw(dxdraw1.Surface,0,0,0); dxdraw1.Flip; sleep(3000); close; end; //POCZĄTEK GRY if unit1.start=1 then begin muza.Open; muza.Play; grafika.Items.Find('logo').Draw(dxdraw1.Surface,0,0,0); dxdraw1.Flip; sleep(2000); unit1.start:=0; end else DXDraw1.Flip; DXDraw1.Surface.Fill(clBlack); |
Wykorzystujemy zmienną start do informowania nas o stanie gracza oraz wczytywania początkowego rysunku podczas uruchamiania gry. Obiekt muza to TMediaPlayer. Jest odpowiedzialny za odtwarzanie muzyki.
Następnie otwórzmy procedurę OnCreate naszej formy. Umieścimy tam polecenia ładujące pliki graficzne :
1 2 3 4 5 6 7 8 9 |
Grafika.Items.Find('tlo').Picture.LoadFromFile('grafikatlo.bmp'); Grafika.Items.Find('warstwa1').Picture.LoadFromFile('grafikawarstwa1.bmp'); Grafika.Items.Find('warstwa2').Picture.LoadFromFile('grafikawarstwa.bmp'); Grafika.Items.Find('logo').Picture.LoadFromFile('grafikalogo.bmp'); Grafika.Items.Find('koniec').Picture.LoadFromFile('grafikakoniec.bmp'); |
Do wyjścia z gry będziemy używać klawisza q. Aby to zrobić wejdź w OnKeyPress naszej formy i zapisz :
1 |
if key='q' then close; |
2. Procedury związane z ruchem postaci :
Spadanie podczas opuszczenia terenu :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
procedure TGracz.Spadanie; begin if not(Gracz_a is TWarstwa1) then begin Gracz_a.y:=Gracz_a.y+15; y:=y+15; end; end; |
Wyjaśnienie : Gdy nasz obiekt gracz będzie w powietrzu, on i jego kopia mają spadać w dół. Po co kopia ? – wyjaśnię później.
w pierwszej części sprawdzamy czy gracz nie spadł z planszy. Jeśli tak to kończymy grę. Następnie mamy polecenia : jeśli teren jest prosty to podskakujemy o 12 w górę, jeśli jest górka to o 20. Oto ten kod :
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 |
procedure TGracz_a.DoCollision(Sprite: TSprite; var Done: Boolean); begin if gracz.Y>450 then unit1.start:=2; if Sprite is TWarstwa1 then begin if numer=0 then begin Gracz_a.y:=Gracz_a.y-12; Gracz.y:=Gracz.y-12; Pusty:=1; end; if numer=1 then begin gracz.y:=gracz.y-20 ; gracz_a.Y:=gracz_a.Y-20; end; end; end; |
Poniżej przedstawiam procedurę odpowiedzialną za ruch naszej postaci :
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
procedure TGracz.DoMove(MoveCount: Integer); var klik : Byte; begin inherited DoMove(MoveCount); klik:=0; if isUp in Form1.DXInput.States then begin if Pusty=1 then begin Y := Y - 100; Gracz_a.y := Gracz_a.y-100; Pusty := 0; end; Klik := 1; end; if isDown in Form1.DXInput.States then begin Image := Form1.grafika.Items.find('patrz_w_dol'); AnimCount := Image.PatternCount; AnimSpeed := 0.4; Klik := 1; end; if isLeft in Form1.DXInput.States then begin Image := Form1.grafika.Items.find('lewo'); TGracz_a(Gracz_a).image := Form1.grafika.Items.find('lewo'); AnimCount := image.PatternCount; AnimSpeed := 0.4; numer:=1; Gracz_a.Collision; Gracz_a.x := x - (0.15)*MoveCount;; x := x - (0.15)*MoveCount; Pusty:=0; Klik:=1; end; if isRight in Form1.DXInput.States then begin Image := form1.grafika.Items.find('prawo'); TGracz_a(Gracz_a).image := form1.grafika.Items.find('prawo'); AnimCount := image.PatternCount; AnimSpeed := 0.4; Numer := 1; Gracz_a.Collision; Gracz_a.x := x + (0.15)*MoveCount; x := x + (0.15)*MoveCount; Pusty := 0; Klik := 1; end; if Pusty = 0 then spadanie; Numer:=0; Gracz_a.Collision; //Wyswietla rysunek gracza nieruszającego się if Klik = 0 then begin Image := Form1.grafika.Items.find('srodek'); TGracz_a(Gracz_a).image := Form1.grafika.Items.find('srodek'); AnimCount := Image.PatternCount; AnimSpeed := 0.4; end; end; |
Gdy zostanie wciśnięta strzałka do góry (isUp) wtedy gracz ma podskoczyć o 100 pikseli w górę.
Po wciśnięciu strzałki w dół (isDown) gracz ma przykucnąć. Zmianie ulega tylko grafika.
Przy poruszaniu się w lewo lub prawo (isLeft, is Right) zmieniamy rysunek, następnie wykonujemy lekki podskok. Sprawdzamy czy postać jest w powietrzu. Przesuwamy ją w określonym kierunku. Podajemy informację o wykonanej czynności.
Kopie ukrytą gracza tworzyliśmy po to, abyśmy mogli dokonać animacji naszej postaci. Podczas przemiany jednego rysunku animacji w drugi nie jest możliwe dokładne wykrycie, czy nasz obiekt znajduje się poza warstwą planszy. My wykonaliśmy drugą nieanimowaną oraz niewidoczną postać, która umożliwiała nam kontrolę położenia. Takie rozwiązanie problemu kolizji nie jest idealne (inne sprawniejsze znajdziesz w dziale projekty) i potrzebuje dopracowania, ale to pozostawiam już wam…
Autor: Nakiel