Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
Delphi
Kolize ve hrách v DelphiX
delphi_kolize
31. srpna 2001, 00.00 | Chcete ve vaší hře zjistit, zda raketa narazila do meteoritu, do zdi, nebo střela do nepřítele ? Přečtěte si dnešní článek, ve kterém je popsáno, jak zjistit nejpoužívanější kolize - bodu v obdélníku, dvou obdélníků a dvou kruhů.
Kolize jsou jedna z vůbec nejdůležitějších věcí ve všech hrách (nepočítáme-li šachy a podobné věci :) Vždy je důležité vědět, zda do sebe dvě a více věcí narazili, abychom podle toho uspůsobili hru a provedli další věc (výbuch, odhození do strany nebo jen zastavení pohybu tělesa). Málokdo si asi dovede představit, že by ve hře prošel zdí (teď myslím bez cheatů), propadl by se pohlahou nebo že by vystřelená střela prošla jen tak tělem nepřítele. Existuje samozřejmě jako vždy hned několik možností pro několik případů. Každá možnost má své výhody a nevýhody, a proto si dnes ukážeme několik řešení. Tedy, dáme se do toho.Kolize bod v obdélníku
I když jsem to již několikrát psal, opakování je matka moudrosti, a proto začneme touto jednoduchou věcí. Pokud chceme zjistit, nachází-li se daný bod v určitém obdélníku, použijeme k tomu funkci PtInRect. První parametr je obdélník typu TRect a druhý je bod typu TPoint. Funkce vrací hodnotu True, pokud došlo ke kolizi a false pokud ne.
Kolize dvou obdélníků
A na řadu přichází již trochu složitější věc. Naštěstí i na případ kolize dvou obdélníků windows pamatují, a tak tu máme funkci IntersectRect. Její druhý parametr je první zkoumaný obdélník, třetí parametr je druhý zkoumaný obdélník. Pokud došlo ke kolizi, vrací funkce hodnotu true, a "kolizní" obdélník určuje první parametr. Pro lepší pochopení je zde obrázek:
Věc je již složitější, proč si tedy neudělat nějaký ten vzorový příklad. Definujeme si tedy tři obdélníky typu TRect, a to MoveRect,StayRect a CollisionRect. Dále si definujeme proměnnou Collision typu boolean, podle které poznáme, došlo-li ke kolizi. Na formulář dáme komponenty DXDraw, DXTimer, DXImageList a DXInput, DXInput proto, že s jedním obdélníkem budeme pro názornost hýbat. Do DXImageList si přidáme obrázek, který pojmenujeme grid a který budeme kreslit na pozadí. Stáhnout si jej můžete zde:
Dále si vytvoříme proceduru Form.OnCreate, ve které nastavíme náhodné pozice obou obdélníků. Procedura bude vypadat nějak takto:
|
Dále si vytvoříme proceduru DXTimer.OnTimer ve které všechno nakreslíme a hlavně otestuejeme kolizi. Celý výpis procedury je zde:
|
Nyní můžete projekt uložit, přeložit a spustit. Zkuste hýbat šipkami s jedním obdélníkem, a všimněte si, že program doopravdy funguje. Zde jsou ukázány dvě možnosti programu:
Tentokrát je k downloadu pouze zdrojový kód programu, který hledejte dole v sekci Download.
Kolize dvou kruhů
Bohužel, windows ani Delphi nepamatují na všechno, a tak nám v určitých případech nezbývá nic jiného, než abychom si pomohli sami. Tak je to i v případě kolize dvou kruhů. Naštěstí však máme ještě matematiku, a taky pythagorovu větu, takže to nebude žádný problém. Nejprve si spočítáme vzdálenost středů kruhů a poté ji porovnáme se součtem poloměrů. Pokud bude vzdálenost menší, došlo ke kolizi. Více snad pochopíte z následujícího obrázku:
Opět si tedy vytvoříme ukázkový projekt (mnoho věcí bude stejných nebo částečně podobných, proto nebudu vše znovu opakovat). Na začátek si opět definujeme pár proměnných. Zaprvé MoveCircle a StayCircle jako record složený ze středu (CenterX a CenterY) a poloměru (Radius). Vše typu integer. Dále Collision typu boolean, podle které poznáme, došlo-li ke kolizi a pomocnou proměnnou r typu real. Všechny proměnné hezky pohromadě máte zde:
|
Dále si opět vytvoříme proceduru Form.OnCreate, ve které si nastavíme náhodné polohy obou kruhů:
|
A nakonec konečně přistoupíme k proceduře DXTimer.OnTimer. K čemu slouží již doufám všuchni víte, a proto jen zopakuji, že v ní nejprve zkontrolujeme, zde-li nedošlo ke kolizi a poté oba kruhy nakreslíme. Výpis celé procedury je zde:
|
Zde jsou ještě dva screenshoty aplikace:
Jednoduchou úpravou naší procedury můžeme samozřejmě vytvořit funkci PtInCircle, která bude zkoumat, zda-li se daný bod nachází v kruhu. Bude na stejném principu, pouze nemusíme sčítat oba poloměry, jelikož bod žádný poloměr nemá. To je ale již na vás...
Závěr
Samozřejmě jsem nenapsal všechny možnosti, které můžete použít, jelikož by jich bylo nespočet. Každá se hodí pro torchu něco jiného. Například nejpřesnější je zjišťovat, zde-li některý pixel jednoho obrázku překrývá některý pixel obrázku druhého. Tato metoda je všek velice pomalá. Výhoda metod popsaných v tomto článku spočívá hlavně v rychlosti, bohužel u kolize dvou kruhů je často velká nepřesnost. Více pochopíte z tohoto obrázku:
Podle našeho postupu ke kolizi došlo, ve skutečnosti však nikoliv. Takovéto situace se řeší tím, že se jeden objekt rozdělí na více malých kruhů, čím více kruhů, tím větší přesnost:
A vše je již vyřešeno. Tímto zárověň ukončuji dnešní článek.
Download
Zde si můžete stáhnout dnes vytvořený příklad ( pouze zdrojáky ) - (14 kB).
Relevantní články
Seriál - Tvorba her v DelphiX
Seriál - Tvorba hry Had v DelphiX
Zobrazení části obrázku v DelphiX
Komponenta DXImageList
Simulace sněžení v DelphiX
Zobrazení kurzoru v DelphiX
Posuvný text v DelphiX
Isometrický engine v DelphiX
Sprity v DelphiX (C++ Builder)
Obsah seriálu (více o seriálu):
- Tvorba her v DirectX v Delphi - 1. díl
- Tvorba her v DelphiX - 2. díl
- Tvorba her v DelphiX - 3. díl
- Tvorba her v DelphiX - 4. díl
- Tvorba her v DelphiX - 5.díl
- Bludiště v DelphiX
- Kolize ve hrách v DelphiX
- Posuvný text v DelphiX bez komponenty
- Posuvný text v DelphiX podruhé
- Speciální grafické efekty v DelphiX
- TurboPixels aneb rychlé pixely v DelphiX
- Let s vrtulníkem v DelphiX
- Stíny a světla trochu jinak
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007