Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
Laethnes
Založen: 14. 02. 2008 Příspěvky: 38
|
Zaslal: 24. březen 2009, 11:47:07 Předmět: [POŘEŠENO] OOP návrh (poskládání) herního enginu |
|
|
Dobrý den,
omlouvám se, pokud tu dané téma již bylo, ale nemohu ho nikde pořádně najít.
Jedná se o návrh herního enginu na úrovni OOP; chtěl bych poradit jak realizovat některé komunikace, ale v podstatě se jedná o obecnější problém, než je herní engine.
Viděl bych to tak, že bych vytvořil nějakou třídu Mapa, která by byla primárně rozdělena na několik částí: grafický engine, kolizní engine, samotná logika, příp. GUI (to si nejsem jist, zda chci dát sem, nebo do třídy aplikace). Mapa obsahuje seznam objektů, které se skládají opět z několika částí: grafika (model pro vykreslení), kolize a metody a data pro ovládání (AI, players, příp. net). Při vykreslení smínku by to probíhalo následovně: nejprve by se projel seznam objektů a spustila se funkce Run pro ovládání pro daný snímek. Kolizní engine by pak vyhodnotil pády apod. a nakonec grafický engine vše vykreslil. Tak se to asi dělá běžně, ne?
Mno a můj problém: ve fázi ovládání postavy se objeví nutnost výběru několika objektů ze svého okolí. Ale jak má instance třídy objekt přistupovat k hernímu enginu (který by udělal výběr na základě kolizního systému)?
Napadají mě následující možnosti:
- každá instance objektu bude mít odkaz na mapu
- mapa bude singleton (tohle se mě vůbec nelíbí, protože občas budu chtít mít nahraných map více)
- obecně herní engine bude singleton a ten bude poskytovat odkaz na mapu
- odkaz na mapu se objektům bude předávat při volání Run (ovšem znemožňuje to volání nějakých metod z kolizního systému jako např. reakce na náraz)
Ani jedna se mě moc nelíbí, singletonům se snažím vyhnout. Zvlášť uvažuji-li že bych chtěl zkusit i engine ve stylu klient-server a tudíž sever potřebuje, aby běželo několik map zároveň.
Implementace v C++ (chci využívat vícenásobnou dědičnost ve spojení se šablonami)
Pokud to potřebujete vědět, měla by to být adventura ve stylu Legend of Zelda (myslím tím izometrický pohled, ovládání jako v nějaké konzolové RPG apod.)
Naposledy upravil Laethnes dne 25. březen 2009, 18:27:22, celkově upraveno 1 krát |
|
Návrat nahoru |
|
|
Peta
Založen: 28. 07. 2007 Příspěvky: 154 Bydliště: V prvnim patre hned vedle koupelny.
|
Zaslal: 24. březen 2009, 15:40:44 Předmět: |
|
|
Možná bys mohl zkusit se podívat na podstatu problému a neřešit jeho důsledky, ale příčinu. Plánuješ mít třídu Mapa která obsahuje objekty - tudíž si uměle vynucuješ to, aby se k objektům přistupovalo přes Mapu. Když bys tyto dvě entity oddělil, tahle nutnost ti odpadne. Navrhni si to tak, aby spolu mohly objekty jednoduše komunikovat a to ti vyřeší tenhle problém (tj. třeba nějaký seznam objektů nezávislý na mapě na který bude mít každý objekt odkaz třeba). _________________ Když je Ti smutno, otoč se tváří ke slunci a všechny stíny padnou za Tebe. |
|
Návrat nahoru |
|
|
Laethnes
Založen: 14. 02. 2008 Příspěvky: 38
|
Zaslal: 24. březen 2009, 16:24:07 Předmět: |
|
|
Peta napsal: |
Možná bys mohl zkusit se podívat na podstatu problému a neřešit jeho důsledky, ale příčinu. Plánuješ mít třídu Mapa která obsahuje objekty - tudíž si uměle vynucuješ to, aby se k objektům přistupovalo přes Mapu.Když bys tyto dvě entity oddělil, tahle nutnost ti odpadne. Navrhni si to tak, aby spolu mohly objekty jednoduše komunikovat a to ti vyřeší tenhle problém (tj. třeba nějaký seznam objektů nezávislý na mapě na který bude mít každý objekt odkaz třeba). |
Mno, to co navrhuješ je v podstatě to, co jsem již psal ("- každá instance objektu bude mít odkaz na mapu") a to už je jedno, jestli se jedná o odkaz na mapu, či seznam objektů. Vlastně mně ta mapa přijde výhodnější, protože obsahuje kolizní systém, takže když např. v jednom objektu (hlavní postava) dodje k útoku, prostě požádá kolizní systém v mapě o seznam objektů v daném rozsahu a ten třeba předá metodě útoku, která spočítá zranění a poupravuje stavy objektů. Kdyby každý objekt měl odkaz na seznam objektů, ještě by potřeboval přístup k nějaké výpočetní jednotce, která by spočítala objekty v okruhu (příp. by si to objekt musel spočítat sám).
Takže to je jedno - klidně mohu mít mapu a seznam objektů jako dvě položky úplně jiné třídy, ale pořád mě chybí vazba na tu mapu (kolize, ostatní objekty) a zcela naopak to nejde (mapa obsahuje objekty a objekt se nachází na mapě).
Ten návrh vypadá takto:
kód: |
Mapa
- grafický engine
- kolizní engine
- seznam objektů
- další výpočetní jednotky
|
(Mno dobře, když to vidím, asi bych Mapa přejmenoval na HeníEngine :3)
a když bych to udělal takto:
kód: |
Nadtřída
- Mapa
- grafický engine
- kolizní engine
- další výpočty
- seznam objektů
|
pořád chybí zpětná vazba na rodiče. Tohle potřebuju - nějak získat vazbu na rodiče, ať už to poskládám jakkoli. Mno a to, aby si každý objekt uchovával odkaz na rodiče mě nepřijde nejideálnější (asi to udělám, když to nepůjde jinak)...
EDIT: "Možná bys mohl zkusit se podívat na podstatu problému a neřešit jeho důsledky, ale příčinu." Jo, to je dobrý nápad, ale (vždycky je ale :3) tohle vzniklo (příčina =) z toho, že ve své předchozí hře jsem objekty měl uložené jako strukturu a ne třídu (ano, vím, že v C++ je to takřka totéž, ale teď narážím na podstatu), takže vše se odehrávalo jen v jedné třídě (mapa/engine):
kód: |
funkce reload():
projdi_vsechny_objekty:
if(objekt == hrac):
zpracuj_nejak;
else:
zpracuj_nejak_jinak;
|
Ale nakonec jsem to dodělal jen jako maturitní projekt a nepokračoval jsem kvůli boji se složitostí. Teď se tomu chci vyhnout pěknému nalajnovanému rozdělení. A tak jsem zodpovědnost za chování nechal samotným objektům (a tím objekty budou i potřebovat přistupovat k mapě: pathfinding atd.) s tím, že mapa bude zpracovávat minimum věcí a spíš se z mapy stane takový rozcestník práce:
kód: |
Cyklus_mapy:
pro_vsechny_objekty:
objekt.zpracuj_vstup();
kolize.zpracuj();
grafika.vykresli();
reload_udalosti();
|
+ případné specializované metody (např. v zpracování počasí, časově založené události apod.) |
|
Návrat nahoru |
|
|
Peta
Založen: 28. 07. 2007 Příspěvky: 154 Bydliště: V prvnim patre hned vedle koupelny.
|
Zaslal: 24. březen 2009, 17:53:39 Předmět: |
|
|
Při designování se musíš vždycky v nějakém okamžiku rozhodnout, zda chceš mít chytré objekty, nebo algoritmy. Jednoduše řečeno, můžeš mít několik různých obejktů které používáš v nějakém algoritmu. Otázka je, jestli z objektů uděláš "jen" lepší datové struktury a veškerou logiku aplikace obstará hlavní programová smyčka, nebo naopak budou tvé objekty chytré "blackboxy" s komunikačním interfacem, kdy si ty objekty budou umět spoustu věcí spočítat samy a algoritmus bude "pouze" ve správném pořadí volat jejich metody. Samozřejmě to jsou extrémy a většinou se používá něco mezitím (s inklinací k jednomu nebo druhému směru).
Tvůj návrh:
kód: |
Nadtřída
- Mapa
- grafický engine
- kolizní engine
- další výpočty
- seznam objektů
|
Není to špatné, já jsem třeba použil něco podobného (a taky jsem narazil na to co ty) když jsem dělal svoji vlastní hru:
kód: |
World
- Mapa
- Hráč
- Nepřátelé (aka aktivní objekty)
- Statické objekty
- Particles (aka střely)
|
Tebou popisovaný "nešvar" nutnosti v každém objektu si pamatovat rodiče je mi záhadou. Respektive, možná je to jen špatná formulace, nicméně já to řešil tím stylem, že když si objekty jenž existovaly v mém světě chtěly povídat s hráčem, statickými objekty nebo mapou, šly na to přes společného rodiče World (ukazatel na něj dostali při narození) jenž sloužil čistě jako zapouzdřovač. Volil jsem cestu středně chytrých objektů, tj spoustu si toho počítaly samy ale některé věci (třeba kolize) řešila hlavní smyčka tím že se objektů ptala na požadováné údaje (pozice atd).
Neříkám, že to je dobrý způsob. Myslím si ale, že není úplně špatný. Možná tě to k něčemu inspiruje a možná ne. _________________ Když je Ti smutno, otoč se tváří ke slunci a všechny stíny padnou za Tebe. |
|
Návrat nahoru |
|
|
Laethnes
Založen: 14. 02. 2008 Příspěvky: 38
|
Zaslal: 24. březen 2009, 18:16:51 Předmět: |
|
|
Peta napsal: |
Při designování se musíš vždycky v nějakém okamžiku rozhodnout, zda chceš mít chytré objekty, nebo algoritmy. Jednoduše řečeno, můžeš mít několik různých obejktů které používáš v nějakém algoritmu. Otázka je, jestli z objektů uděláš "jen" lepší datové struktury a veškerou logiku aplikace obstará hlavní programová smyčka, nebo naopak budou tvé objekty chytré "blackboxy" s komunikačním interfacem, kdy si ty objekty budou umět spoustu věcí spočítat samy a algoritmus bude "pouze" ve správném pořadí volat jejich metody. Samozřejmě to jsou extrémy a většinou se používá něco mezitím (s inklinací k jednomu nebo druhému směru).
|
Jj, myslel jsem spíš ty "blackboxy". Využitím virtuální dědičnosti. To vychází z mého už postaršího nápadu vycházejícího z té mé dříve zmíněné hry - tam jsem měl ovládání těžce napevno. A později jsem si uvědomil, že toto by mohlo úžasně zjednodušit doimplementovávání dalších možností, jako je třeba nastavitelné ovládání (ano, tohle není zrovna nejlepší příklad :3) možnost snadno přidat multiplayer jak lokální (jeden PC), tak po síti, možnost přidávat nové algoritmy pro NPC apod. A především nádherný příklad zapouzdření.
Peta napsal: |
... já jsem třeba použil něco podobného (a taky jsem narazil na to co ty) když jsem dělal svoji vlastní hru:
kód: |
World
- Mapa
- Hráč
- Nepřátelé (aka aktivní objekty)
- Statické objekty
- Particles (aka střely)
|
|
Mno, na rozdělení na statické a aktivní objekty jsem taky myslel, ale nepsal jsem to, protože mě to přišlo pro problém irelevantní.
Peta napsal: |
Tebou popisovaný "nešvar" nutnosti v každém objektu si pamatovat rodiče je mi záhadou. Respektive, možná je to jen špatná formulace, nicméně já to řešil tím stylem, že když si objekty jenž existovaly v mém světě chtěly povídat s hráčem, statickými objekty nebo mapou, šly na to přes společného rodiče World (ukazatel na něj dostali při narození) jenž sloužil čistě jako zapouzdřovač. Volil jsem cestu středně chytrých objektů, tj spoustu si toho počítaly samy ale některé věci (třeba kolize) řešila hlavní smyčka tím že se objektů ptala na požadováné údaje (pozice atd).
|
Asi je to špatná formulace :3, poněvadž to, co myslím "pamatovat si rodiče" je vlastně to, že všechny objekty mají ukazatel na World :3.
Mno a kolizi chci do samostatného modulu dát ze dvou důvodů; jednak se jedná o investici do budoucna - objevují se různé fyzikální enginy běžící na grafice apod. a toto oddělení mě přijde jako dobrý nápad, protože změna kolizního enginu neovlivňuje zbytek světa (nepočítám lepší kolize, rychlejší apod :3) a druhak klasická znovupoužitelnost. Jak jsem dodělal tu starou hru, zjistil jsem, že z ní možu použít... nic. Kolizní systém byl tak provázaný zbytkem enginu, že bych sotva mohl extrahovat samotné výpočty, zda se dva konkrétní objekty dotýkají, víc asi ne. Umožňuje to vytvořit nejprve narychlo udělaný pomalý kolizní systém a ten pak nahradit později něčím lepším (třeba jen proto, že jsem původně o nových možnostech nevděděl).
Peta napsal: |
Neříkám, že to je dobrý způsob. Myslím si ale, že není úplně špatný. Možná tě to k něčemu inspiruje a možná ne. |
Mno, právě to ukládání ukazatele na World u každého objektu je to, proč tu vůbec existuje tohle vlákno :3. Jde o to, že jsem se chtěl zeptat, jak obecně se řeší to, když máš třídu A (World), která obsahuje hromady instancí tříd B (objekt), chceš z instance B mít přístup do A, ale instanci A nechceš mít ani globální/singleton a ani mít ukazatel uložený v instancích B. Mno a tady jsem rovnou uvedl konkrétní případ (stejně když mám problém, vždycky mě napíšou "uveď příklad" :3) |
|
Návrat nahoru |
|
|
Marek
Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 24. březen 2009, 20:49:35 Předmět: |
|
|
Pozor na pojmy, virtuální dědičnost nejspíš nechceš použít. (class derived : virtual public base {} _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
|
Laethnes
Založen: 14. 02. 2008 Příspěvky: 38
|
Zaslal: 24. březen 2009, 20:57:21 Předmět: |
|
|
Eosie napsal: |
Pozor na pojmy, virtuální dědičnost nejspíš nechceš použít. (class derived : virtual public base {} |
Eh, promiň, nikdy jsem se o tom od té doby, co jsem se o tom učil, nebavil, takže mě to občas ujede. I když popravdě řečeno ju možná budu chtít použít, ale máš pravdu, to o čem jsem mluvil jsou klasické virtuální metody... *kapka* |
|
Návrat nahoru |
|
|
Augi
Založen: 28. 07. 2007 Příspěvky: 782 Bydliště: Čerčany
|
Zaslal: 24. březen 2009, 22:04:00 Předmět: |
|
|
Já bych hru koncipoval nějak takto:
- herní engine
- fyzikální engine
- grafický engine
- sound engine
- input
- multiplayer
Je to myšleno tak, že objekty v herním enginu jsou kompozice objektů z ostatních sub-enginů. Logika na úrovni herního enginu může být pak postavena např. tak, že umožní běh fyzikálního enginu v samostatném vlákně - především tím, že zajistí synchronizaci. |
|
Návrat nahoru |
|
|
Laethnes
Založen: 14. 02. 2008 Příspěvky: 38
|
Zaslal: 24. březen 2009, 22:19:48 Předmět: |
|
|
Jj, však to je jeden z důvodů, proč to chci mít rozdělené. Akorát ještě hodně promýšlím logiku, jak to udělat (např.: běží vlákno řešící co který objekt chce udělat a paralerně s tím se vykresluje grafika (předchozí snímek), až oba skončí, kolizní engine spočítá pohyby a upraví souřadnice (a pošle příp. zprávy objektům). Nebo by souřadnice objektů mohly být uloženy 2x - jednou již spočítané (podle kterých se vykresluje) a aktuálně počítané, takže zatímco by běžela grafika, paralerně by postupně běžel herní a pak kolizní engine (koneckonců grafika je hodně úzkým hrdlem, ne?) ). Mno, každopádně to jsou jen úvahy a OT. |
|
Návrat nahoru |
|
|
pcmaster
Založen: 28. 07. 2007 Příspěvky: 1824
|
Zaslal: 25. březen 2009, 01:03:52 Předmět: |
|
|
Paralelne!
Podla mna grafika nie je uzkym hrdlom, pretoze bezi skoro cisto na GPU, takze ma CPU (ci SPUs) volne "ruky". Uzkym hrdlom moze byt prave fyzika a AI.
Tvoj navrh "double-buffering" na hodnoty pre renderer a zvysok je asi spravny, tak by som to vymyslel aj ja.
(Priznam sa, ze tie dlhocizne prispevky vyssie som necital.) _________________ Off-topic flame-war addict since the very beginning. Registered since Oct. 2003!
Interproductum fimi omne est. |
|
Návrat nahoru |
|
|
Marek
Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 25. březen 2009, 03:47:10 Předmět: |
|
|
Nezapomínejte, že úzké hrdlo se může měnit v závislosti na hardware. Rozumně zdůvodněný předpoklad, že někde bude nějaký bottleneck, ti pouze pomůže zaměřit se na něj včas.
Pro větší počet objektů bude bottleneck pravděpodobně na CPU a je to zároveň ten nejčastější, s jakým se můžeš setkat, protože jde dosáhnout pouhou blbostí programátora a často se to neprávem zdůvodňuje tím, že za všechno může GPU (moje zkušenost). Při použití náročnějších efektů nebo obecně špatně udělaných efektech bych pak i věřil bottlenecku na GPU (tady je potřeba si ujasnit, jestli je vůbec v tvých silách ty efekty dělat).
Kdo neví, jak navrhnout game engine, ať si nastuduje zdrojáky několika free enginů a k tomu ať si přihodí nějakou odbornou literaturu. Je celkem jedno, kde začnete... _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
|
Peta
Založen: 28. 07. 2007 Příspěvky: 154 Bydliště: V prvnim patre hned vedle koupelny.
|
Zaslal: 25. březen 2009, 10:39:28 Předmět: |
|
|
Eosie napsal: |
Kdo neví, jak navrhnout game engine, ať si nastuduje zdrojáky několika free enginů a k tomu ať si přihodí nějakou odbornou literaturu. Je celkem jedno, kde začnete... |
Souhlasim, tohle rozhodne pomuze. Asi ani neni nutne cist tluste knihy od zacatku az do konce, ale nejaky teoreticky background se bude urcite hodit a pak bych sel asi cestou pruzkumu existujicich enginu. Pokud chces delat opravdu neco vetsiho, tak je dost pravdepodobne ze nebudes schopny vychytat vsechny detaily a v prubehu implementace narazis na nejake vazne problemy (me se to treba u vyse zminovane hry stalo dokonce nekolikrat). _________________ Když je Ti smutno, otoč se tváří ke slunci a všechny stíny padnou za Tebe. |
|
Návrat nahoru |
|
|
Laethnes
Založen: 14. 02. 2008 Příspěvky: 38
|
Zaslal: 25. březen 2009, 11:31:01 Předmět: Eh... |
|
|
Ale tohle rozhodně není můj problém, jestli chápu správně, že se to tu začalo řešit. Nějaký návrh celkového enginu mám a stále na něm pracuji (a začíná se mě líbit :3), v tomto topicu jsem chtěl hlavně řešit problém jak může instance třídy B přistupovat k instanci třídy A, je-li instance B v datech Ačka.
Na samotný návrh se neptám (resp. tento topic jsem nevytvořil k tomu, aby to pořešil), spíš jsem to zmínil jen pro úplnost :3.
EDIT:
Eosie napsal: |
Nezapomínejte, že úzké hrdlo se může měnit v závislosti na hardware. Rozumně zdůvodněný předpoklad, že někde bude nějaký bottleneck, ti pouze pomůže zaměřit se na něj včas.
Pro větší počet objektů bude bottleneck pravděpodobně na CPU a je to zároveň ten nejčastější, s jakým se můžeš setkat, protože jde dosáhnout pouhou blbostí programátora a často se to neprávem zdůvodňuje tím, že za všechno může GPU (moje zkušenost). Při použití náročnějších efektů nebo obecně špatně udělaných efektech bych pak i věřil bottlenecku na GPU (tady je potřeba si ujasnit, jestli je vůbec v tvých silách ty efekty dělat). |
Eh, tady se taky projevila moje neznalost (sám to moc prověřené nemám, spíš jsem to psal jen jako názor), každopádně si myslím, že dobře navržený engine - rozdělený na jednotlivé části jako je vykreslování, výpočet chování, kolize apod. - by neměl mít problém měnit co se bude řešit paralelně a v jakém vláknu (jak jsem psal - např. video v jednom a chování a kolize v druhém a pak třeba přijdu na to, že to není moc efektivní a je lepší v jednom mít grafiku a pak kolize (např. proto, že kolize se budou řešit na GPU) a v druhém vlákně mít chování apod.). Koneckonců by se třeba mohl použít dynamické uspořádání - program bude měřit jak dlouho které části výpočty trvají a pak je optimálně rozdělit do vláken. (A jak se začnou výrazně rozšiřovat čtyř a více jádrové procesory, bude problém vůbec mít dost modulů, které lze paralelizovat (omlouvám se, nevím, jak to napsat spisovně) :3. Upozorňuji, že tohle jsou zase spíš jen úvahy, než že bych chtěl poradit, nebo tak něco |
|
Návrat nahoru |
|
|
Augi
Založen: 28. 07. 2007 Příspěvky: 782 Bydliště: Čerčany
|
Zaslal: 25. březen 2009, 14:05:02 Předmět: Re: Eh... |
|
|
Laethnes napsal: |
Ale tohle rozhodně není můj problém, jestli chápu správně, že se to tu začalo řešit. Nějaký návrh celkového enginu mám a stále na něm pracuji (a začíná se mě líbit :3), v tomto topicu jsem chtěl hlavně řešit problém jak může instance třídy B přistupovat k instanci třídy A, je-li instance B v datech Ačka. |
Pokud se chceš vyhnout singletonu (silně doporučuji), tak moc jiných možností než předat ukazatel/referenci na nadřazenou třídu v konstruktoru podřízené třídy nezbývá... |
|
Návrat nahoru |
|
|
Peta
Založen: 28. 07. 2007 Příspěvky: 154 Bydliště: V prvnim patre hned vedle koupelny.
|
Zaslal: 25. březen 2009, 17:22:55 Předmět: Re: Eh... |
|
|
Augi napsal: |
Pokud se chceš vyhnout singletonu (silně doporučuji), tak moc jiných možností než předat ukazatel/referenci na nadřazenou třídu v konstruktoru podřízené třídy nezbývá... |
Tak tak, však k podobnému závěru jsme společně taky došli, když si mi radil s tančíky _________________ Když je Ti smutno, otoč se tváří ke slunci a všechny stíny padnou za Tebe. |
|
Návrat nahoru |
|
|
|