W tym artykule ożywimy trochę naszą gierkę. Wprowadzimy wrogie postacie. Zasada ich funkcjonowania będzie podobna jak w Mario tzn. jeżeli naskoczymy na wroga to on zginie, jeśli natomiast on dotknie nas, wtedy my giniemy. Będzie on poruszał się po terenie na swoim poziomie. Gdy dojdzie do jednego brzegu to skręci i będzie szedł do drugiego i tak w kółko.
Do pliku grafika.vtd dograłem grafikę nowej postaci, opis pominę, ponieważ pisałem o tym wcześniej.
Na początek otwórzmy plik zmienne.pas i dodajmy następujące pozycje :
1 2 3 4 5 6 7 8 9 10 11 |
// Stan gracza st_zywy = 0; st_wybucha = 1; st_martwy = 2; // Jedenaście wrogich postaci Wrogowie : array[0..10] of TGracz; |
Następnym krokiem będzie przetworzenie procedury TGracz.Tworz w unicie PlikTGracz, aby było można ją wykorzystać zarówno dla postaci grającej i wrogów. Nowe elementy procedury zostały zaznaczone pogrubioną czerwoną czcionką. Dodaliśmy grafikę wybuchu, niektórym zmiennym wartości będziemy przypisywać przy odwoływaniu się do procedury np. zmienna Tryb, określająca czy postać jest kierowana przez człowieka czy jest wrogiem.
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 |
procedure TGracz.Tworz(Grafika1, X1, Y1, Predkosc1, Tryb1 : Longint); begin GrafikaBaza := TVTDb.Create(PD); GrafikaBaza.FileName := Dir+'grafikagrafika.vtd'; //---------W lewo---------- Grafika[1] := TAGFImage.Create(PD); Grafika[1].LoadFromVTDb(GrafikaBaza,'gracz_'+inttostr(Grafika1)+'l', D3DFMT_A8R8G8B8); //---------W prawo-------- Grafika[2] := TAGFImage.Create(PD); Grafika[2].LoadFromVTDb(GrafikaBaza,'gracz_'+inttostr(Grafika1)+'p', D3DFMT_A8R8G8B8); //---------Wybuch--------- Grafika[3] := TAGFImage.Create(PD); Grafika[3].LoadFromVTDb(GrafikaBaza,'boom', D3DFMT_A8R8G8B8); Pozycja.X := X1; Pozycja.Y := Y1; maxSkok := 150; Skok := 0; Predkosc := predkosc1; KierunekX := w_prawo; KierunekX_old := w_prawo; Tryb := Tryb1; AnimPos :=0; end; |
Kolejną procedurą w której dokonamy zmian jest Rysuj. Określamy, czy postać jest w stanie żywym czy w trakcie wybuchu i przypisujemy odpowiednie do tego stanu grafiki. Do stanu st_martwy nie przypisujemy nic, aby jednostka znikła całkowicie z 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 |
procedure TGracz.Rysuj; begin If StanZycia = st_zywy then begin If KierunekX_old = w_lewo then Gra.Draw(Grafika[1],Pozycja.X-(mapa_X*50),Pozycja.Y,AnimPos, EffectSrcAlpha); If KierunekX_old = w_prawo then Gra.Draw(Grafika[2],Pozycja.X-(mapa_X*50),Pozycja.Y,AnimPos, EffectSrcAlpha); end; If StanZycia = st_wybucha then Gra.Draw(Grafika[3],Pozycja.X-(mapa_X*50),Pozycja.Y,AnimPos, EffectSrcAlpha); end; |
Śledząc kod dalej dojdziemy do procedury Idz , jest ona najważniejsza. Będziemy w niej określać typ kolizji gracza z wrogiem, kierować wrogą postacią. Na początku określamy które polecenia ma wykonywać dla postaci wrogich, kierowanych przez komputer, a które dla osoby grającej:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
IF TRYB = tryb_czlowiek THEN ... end; IF TRYB = tryb_komputer THEN begin ... end; |
Polecenia postaci grającej pozostają bez zmian. Zajmiemy się więc postacią wrogą. Po pierwsze określmy ruch. Będzie się poruszać w prawo lub w lewo, tak długo, aż pole poniżej i przed będzie puste (czyli, aż znajdzie się na końcówce terenu). W takiej sytuacji zmieni kierunek na przeciwny, czyli tak samo jak w tradycyjnym Mario.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//Poruszanie się w prawo If (KierunekX = w_prawo)and(GraPlik.Plansza[PozycjaNaMapie.X+1, PozycjaNaMapie.Y] in Mozliwy_ruch) then INC(Pozycja.X, PredkoscA) else KierunekX := w_lewo; //Poruszanie się w lewo If (KierunekX = w_lewo)and(GraPlik.Plansza[PozycjaNaMapie.X-1, PozycjaNaMapie.Y] in Mozliwy_ruch) then DEC(Pozycja.X, PredkoscA) else KierunekX := w_prawo; |
Postać już chodzi, teraz ustawimy reakcje na kontakt postaci grającej z wrogą. Rozważymy dwa przypadki. Pierwszy gdy znajduje się klatkę nad (czyli naskakuje na wrogą postać), wtedy ma wroga postać wybuchnąć :
1 2 3 4 5 |
If (Gracz.PozycjaNaMapie.X = PozycjaNaMapie.X)and (Gracz.PozycjaNaMapie.Y+1 = PozycjaNaMapie.Y) then StanZycia := st_wybucha; |
Druga sytuacja, gdy znajdują się na tej samej klatce (doszło do kontaktu bocznego, bez skoku), wtedy nasz postać ma zginąć :
1 2 3 4 5 |
If (Gracz.PozycjaNaMapie.X = PozycjaNaMapie.X) and (Gracz.PozycjaNaMapie.Y = PozycjaNaMapie.Y) then if StanZycia = st_zywy then Ekran := ek_koniec; |
A oto cała procedura z wyróżnionymi nowymi elementami :
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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
procedure TGracz.Idz; var PredkoscA : Byte; begin // Animacja postaci If (kierunekX = 0) and (RuchY = 0) then begin if AnimStan in [1..10] then AnimPos := 0; if AnimStan in [11..20] then AnimPos :=1; if AnimStan = 21 then begin AnimStan:=1; // Ukrycie postaci, która wybuchła If StanZycia=st_wybucha then StanZycia := st_Martwy; end; Inc(AnimStan) end else if RuchY = 0 then AnimPos := 1 else AnimPos := 0; IF (TRYB = tryb_czlowiek) and (StanZycia = st_zywy) THEN begin // Bieg z przyciskiem Shift If (Klawiatura.Keys[54]) then PredkoscA := Predkosc + 1 else PredkoscA := Predkosc; KierunekX := 0; If (Klawiatura.Keys[205]) and (PozycjaNaMapie.X 1) and ( (GraPlik.Plansza[ PozycjaNaMapie.X, PozycjaNaMapie.Y - 1] in Zakaz_ruchu )or (GraPlik.Plansza[PozycjaNaMapie.X - 1, PozycjaNaMapie.Y - 1] in Zakaz_ruchu ) ) then //w lewo begin KierunekX := w_lewo; KierunekX_old := w_lewo; Dec(Pozycja.X, PredkoscA); end; If Klawiatura.Keys[200] then If (GraPlik.Plansza[PozycjaNaMapie.X, PozycjaNaMapie.Y - 1] in Zakaz_ruchu )and (GraPlik.Plansza[PozycjaNaMapie.X, PozycjaNaMapie.Y] in Mozliwy_ruch ) then RuchY := w_gore; If (PozycjaNaMapie.X > Mapa_X + 12)and(Mapa_X+161) Then Gra.PrzesunMapeStart(w_lewo); end; IF TRYB = tryb_komputer THEN begin PredkoscA := Predkosc; KierunekX_old := KierunekX; //Poruszanie się w prawo If (KierunekX = w_prawo) and (GraPlik.Plansza[PozycjaNaMapie.X + 1, PozycjaNaMapie.Y] in Mozliwy_ruch) then inc(Pozycja.X, PredkoscA) else KierunekX := w_lewo; //Poruszanie się w lewo If (KierunekX = w_lewo)and(GraPlik.Plansza[PozycjaNaMapie.X-1, PozycjaNaMapie.Y] in Mozliwy_ruch) then DEC(Pozycja.X, PredkoscA) else KierunekX := w_prawo; //Wybuch wroga If (Gracz.PozycjaNaMapie.X = PozycjaNaMapie.X)and (Gracz.PozycjaNaMapie.Y+1 = PozycjaNaMapie.Y) then StanZycia := st_wybucha; //Nas wybuch If (Gracz.PozycjaNaMapie.X = PozycjaNaMapie.X)and (Gracz.PozycjaNaMapie.Y = PozycjaNaMapie.Y) then if StanZycia = st_zywy then Ekran := ek_koniec; end; end; |
Najważniejsze mamy już z głowy. Teraz w unicie plikTGra, dodajmy polecenia, aby gra rysowała oprócz postaci grającej również wrogie postacie i wykonywała ich działanie. Zrobimy to poprzez dodanie :
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 |
procedure TGra.RysujGraczy; var i: byte; begin If Gracz.StanZycia st_martwy then Gracz.Rysuj; for i:=0 to 10 do If Wrogowie.StanZycia st_martwy then Wrogowie.Rysuj; end; procedure TGra.Oddychaj; var i:byte; begin Gra.Oddech; If Gracz.StanZycia st_martwy then Gracz.Oddech; for i:=0 to 10 do If Wrogowie.StanZycia st_martwy then Wrogowie.Oddech; end; |
Na zakończenie zajrzyjmy do procedury FormaOnKeyPress, poprawimy tam inicjowanie postaci grającej i zainicjujemy wrogie postacie
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
if Ekran = ek_Start then begin ... //Tworzenie postaci grających Gracz.Tworz(0,200,120,1,tryb_czlowiek); //Tworzenie postaci wrogich for i:=0 to 10 do begin Wrogowie.Tworz(1,random(mapa_w*50),50,1,tryb_komputer); end; ... end; |
To wszystko, po uruchomieniu powinno wszystko działać. Kod się robi coraz bardziej skomplikowany, ale jeśli czytaliście poprzednie części tutorialu nie powinno być problemu z jego zrozumieniem.