Jednoduchá hra

Naše dosavadní znalosti (doplněné o několik drobností) využijeme v této lekci k naprogramování jednoduché hry, ve které budeme pohybovat tlačítkem, abychom posbírali radiobuttony, pokud nás nezastaví nepřítel (čas, učitel nebo jiné problémy :-) ). Hru jsem převzal z www.programujte.com - kurz Delphi, lekce 8.

Hra - pohyb

Podle obrázku vložíme do formuláře čtyři tlačítka pro pohyb, jedno tlačítko, se kterým budeme pohybovat (v ukázkách pojmenované zrout), radiobuttony, které budeme "pojídat" a jeden timer.

Všimněte si, že popisky tlačítek pro pohyb (w,a,d,s) jsou podtržené, jistě si vzpomenete, jak jsme toho v menu textového editoru dosáhli (:-) ) - stačí vložit znak ampersand & před písmeno popisku. Tlačítka budou reagovat na kliknutí myší, ale také na stisk příslušné klávesy, budeme moci "zrouta" ovládat i z klávesnice (klávesami w,a,d,s).
Procedury na tlačítkách pro pohyb jsou podobné a jednoduché, na tlačítku w může být:
procedure TForm2.Button3Click(Sender: TObject);
begin
zrout.Top:=zrout.top-5;
end;
Vlastnost zrout.top určuje vzdálenost tlačítka zrout od horního okraje formuláře. Při každém kliknutí na tlačítko w, nebo při každém stisku klávesy w, se zmenší vzdálenost "zrouta" od horního okraje o 5 pixelů - bude se tedy pohybovat nahoru.
Podobná je procedura na tlačítku pro pohyb doleva:
procedure TForm2.Button1Click(Sender: TObject);
begin
zrout.Left := zrout.Left - 5;
end;
Zbývající dvě procedury pro pohyb jsou velmi podobné, po jejich doplnění už by se měl zrout pohybovat všemi směry buď kliknutím na tlačítko nebo klávesami.


Pokud jsme se začali pohybovat, můžeme začít "žrát" radiobuttony, to už bude trochu složitější, budeme potřebovat znalosti o polích, nový typ TPoint a novou funkci, která zjistí, zda je daný bod uvnitř čtyřúhelníku.

Hra - žereme

Na našem obrázku jsou jenom tři radiobuttony (objekty přímo k sežrání :-) ), ale mohlo by jich být podstatně více, proto by bylo vhodné kontrolovat srážku s nimi v nějakém for cyklu. K tomu ale bude potřeba je uložit do pole, jehož položky budou typu TRadioButton. V sekci var definujeme pole s názvem jidlo:
jidlo: array [1..3] of TRadioButton;
Touto deklarací vytvoříme tři proměnné jidlo[1], jidlo[2], jidlo[3], ve kterých budou uloženy RadioButtony (jejich vlastnosti). Hned někde po startu programu, nejlépe při vytvoření formuláře (doplnit událost FormCreate) do tohoto pole uložíme naše jídlo:
procedure TForm2.FormCreate(Sender: TObject);
begin
jidlo[1]:=RadioButton1;
jidlo[2]:=RadioButton2;
jidlo[3]:=RadioButton3;
end;

Pro kontrolu "srážky" využijeme funkci PtInRect (bod (point) v oblasti (rectangle)), jedním jejím parametrem je bod - pro nás nového typu TPoint. Tento typ si můžeme představit jako minipole (přesněji záznam - viz další lekce) se dvěma položkami - souřadnicemi bodu, na které odkazujeme pomocí tečky (bod.X nebo bod.Y). Pro následující proceduru zrani definujeme (v sekci var) proměnnou typu TPoint a proměnné vysbirano a i:
bod: TPoint;
vysbirano: boolean;
i: integer;

Nyní už můžeme definovat novou proceduru (viz 16. lekce - název doplníme do sekce type, proceduru do sekce implementation):
procedure TForm2.zrani;
begin
vysbirano:= True;
for i := 1 to 3 do
begin
bod.X := jidlo[i].Left + (jidlo[i].width div 2);
bod.Y := jidlo[i].Top + (jidlo[i].Height div 2);
if PtInRect(zrout.BoundsRect,bod) then jidlo[i].Visible := false;
if jidlo[i].Visible = True then vysbirano := False;
end;
if vysbirano = True then showmessage ('hotovo');
end;
Procedura není nijak zvlášť složitá:
- do proměnné vysbirano se uloží true (jako by bylo vysbíráno), proč, to se uvidí dále
- pro každý kousek jídla (for i:=1 to 3) se provádí:
- bod.X := jidlo[i].Left + (jidlo[i].width div 2); - do x-ové souřadnice proměnné bod se uloží vzdálenost jidla od leva + polovina šířky jídla, neboli souřadnice středu radiobuttonu, podobně také y-ová souřadnice, takže proměnná bod je střed radiobuttonu
- komponenta Button má také vlastnost BoundsRect určující jeho "oblast" (obdélník, ve kterém leží)
- if PtInRect(zrout.BoundsRect,bod) then jidlo[i].Visible := false; - jestliže je bod v oblasti buttonu, potom jidlo zneviditelni
- nakonec pro každé jídlo do proměnné vysbirano ulož false, jestli je jidlo viditelné (takže - jestli je alespoň jedno z jidel viditelné, potom není vysbíráno, proto bylo na začátku procedury vysbirano:=true)

Tuto novou proceduru musíme doplnit do všech procedur pro pohyb, například:
procedure TForm2.Button3Click(Sender: TObject);
begin
zrout.Top:=zrout.top-5; zrani;
end;


Posledním základním úkolem bude využít timer k tomu, aby se na tlačítku zrout pravidelně střídaly znaky - a < , což by mohlo znázorňovat klapání čelistí :-) .

Hra - klapání hubou

Procedura pro Timer, která bude na tlačítku zrout vyměňovat znaky, by mohla být jednoduchá:
procedure TForm2.Timer1Timer(Sender: TObject);
begin
if zrout.Caption = '-' then zrout.Caption := '<' else zrout.Caption :='-';
end;
Podstatně hezčí by bylo, kdyby vyměňované znaky odpovídaly směru pohybu, to ovšem necháme už do složitějších úloh.

Ještě poznámku, pomůcku pro ty, kdo si troufnou na jedničkovou úlohu - doplnění nepřítele, který vás při sběru radiobutonů bude pronásledovat - to by opět mohlo být tlačítko.

Hra - nepřítel

"Náraz" dvou tlačítek bychom mohli řešit také pomocí funkce PtInRect, jenže tlačítka jsou větší než Radiobutony, střed tlačítka by měl větší vzdálenost, k nárazu by mohlo dojít opožděně. Proto zkuste využít jinou funkci, která určuje průnik dvou oblastí (obdélníkových):
IntersectRect(nic, zrout.BoundsRect, stihac.BoundsRect)
Prvním parametrem této funkce je oblast průniku - tu v našem případě nevyužijeme (proto název nic), ale musíme tuto proměnnou typu TRect nadefinovat:
nic: TRect;
Další dva parametry funkce IntersectRect jsou oblasti, jejichž průnik určujeme, v našem případě oblast tlačítek zrout a pronásledovatele stihac. Funkce je opět typu boolean (dává výsledek true nebo false), proto je možné psát:
if IntersectRect(nic, zrout.BoundsRect, stihac1.BoundsRect) then ....

Aplikaci ukládej do složky s názvem lekce20 .

Úkoly:

Základní úloha:

Vytvořte aplikaci podle textu lekce (viz ukázka ) - pohyb tlačítka, pojídání radiobutonů a klapání "čelistí" (stejné ve všech směrech).


Úlohy na plus:

Upravte klapání hubou tak, aby odpovídalo směru pohybu.


Doplňte bezhlavě (náhodně) se pohybujícího nepřítele, který vás může chytit.


Úloha na jedničku:

Doplňte projekt tak, aby se nepřítel nepohyboval náhodně, ale přibližoval se k vám.


Úloha pro experty:

Doplňte projekt na jedničku o dalšího nepřítele, možnost nové hry (viz ukázka ), případně ubíhající čas, malý náhodný pohyb koleček, náhodné rozmístění některých nebo všech objektů na začátku hry a podobně dle fantazie.