Eriugena: Návrat domů
Tato Krátká point-and-click adventura příběhově líčí nesnadný návrat filozofa Jana Scota Eriugeny do jeho rodného Irska. Hra je udělaná v C# (s frameworkem MonoGame).
Úvod
V této první části článku představím hru Eriugena s podtitulem Návrat domů.
Námět a děj
Ohledně námětu jsem se nechal (velmi volně) inspirovat klasickou knihou od Umberta Eca Jméno růže. Výsledkem je hra situovaná do kláštera (a částečně jeho okolí), ve které bude nějaké tajemství, popř. i vyšetřování vraždy.
Zvolil jsem postavu filozofa z karolinské renesance, mně osobně sympatickou pro svou unikátní syntézu novoplatonismu s teologií, a to sice Jana Scota Eriugenu. Ten byl dle některých historiků ve Franské říši ubodán mnichy, což jsem pro potřeby změnil na pobodán. Na to jsem navázal příběhem jeho návratu do rodného Irska. Nakonec se celý děj zvrtl až skoro k fantasy, ale konec konců jsem ho vymýšlel až za pochodu a nebyl v tomto případě prioritou. Tou bylo vyzkoušet si vývoj adventury.
Žánr adventury
Hra vznikala necelé čtyři dny. Ten první jsem víceméně jen vytvářel různé místnosti. Do místností jsem pak vložil hlavní postavu a umožnil ji mezi nimi procházet.
Zprvu, bez animace pohybu. Vypadalo to, jako by Eriugena jezdil po klášteru na neviditelném segwayi. Teprve poté jsem začal přemýšlet, jak z toho udělat point-and-click adventuru (které byly tolik populární v 90. letech, s tituly jako Kyrandia či [s RPG prvky] Quest for Glory).
Vymýšlení místností
Místností jsem vymyslel 25 (tedy s indexy 0-24
). Většina z
místností vycházela ze základního layoutu dřevěné
podlahy a kamenné zdi. Jen čtyři venkovní "místnosti" mají jako základ
trávu.
Zde je původní plánek. Obsahuje i informace, ve kterých místnostech se může vyskytovat která nehráčská postava (NPC) a ve kterých místnostech budou jaké předměty (plus rozměry těchto předmětů):
Jazyk, framework a psaní kódu
Jazyk kódu je C# a je užit framework MonoGame. Na kódu je vidět, že jsem si koncept adventury teprve ohmatával za chodu. Proto by mohl být místy vyladěnější a elegantnější.
Rád bych upozornil na jednu zásadu objektového programování, a to sice
zapouzdření (proto by si z tohoto nikdo neměl brát
příklad...). Jedná se o místa, kde jsem např. potřeboval instanci
předmětu změnit stav atributů JeVeSvete
či
JeVInventari
.
Správným postupem by bylo ve třídě Predmety
udělat metodu,
která by stav změnila. Z důvodu jednoduchosti jsem však místo toho změnil
přístupnost přepsáním private set;
na pouhé
set;
u příslušných atributů. U takto malého projektu si
nemyslím, že by tím mohl vzniknout problém, ale je třeba si i zde
připomenout, že to není správný návyk.
Další věc, která by se v kódu dala upravit (a na kterou, budu-li zase dělat adventuru, budu příště myslet), vyplývá ze zásady pojmenované po dalším středověkém mnichovi a v IT velmi důležité, tj. z Ockhamovy břitvy. Jinak řečeno, některé části kódu mám zřejmě zbytečně duplicitní a bylo by možné je řešit metodou. Stejně tak by šel seškrtat počet proměnných.
Logická stránka hry
V této kapitole a jejích podkapitolách se zaměřím na to, co probíhá
ve frameworku MonoGame při fázi
Update()
, tj. na vnitřní logiku hry. Tedy na
všechny změny stavů, v nichž se může nacházet.
Vstup klávesnicí
Jako první jsem vytvořil vstup skrze klávesnici. Nejprve to byly jen šipky doprava a doleva, které umožňovaly chodit vpravo a vlevo. K tomu jsem přidal změnu místnosti při zajití příliš vlevo nebo příliš vpravo na dané obrazovce.
Výjimkou je místnost 24
, tedy
mistnost-lesni-kriz.xnb
, kde už se dále vpravo jít nedá.
Podobně měla původně fungovat místnost 0
("Studovna na
konci chodby"), ale tam jsem nakonec přidal schody, které
vedou do místnosti 16
mistnost-schody.xnb
, protože
chození zleva doprava a zpátky se ukázalo být poměrně
úmorným. I proto jsem skrze klávesu R (jako
"Rychlost") přidal možnost měnit rychlost, a tím počet
obrazových bodů, které Eriugena urazí daným
směrem, má-li aktuálně nastavený pohyb přes
klávesnici či myš.
Rychlostí je celá řada a ta nejpomalejší je zamýšlená spíše jako vtípek (kdyby však někdo v ní dohrál celou hru, byť příběhově ne až tak dlouhou, navrhoval bych mu jako životní možnost stát se tibetským buddhistickým lámou, neboť by předvedl opravdu neobyčejnou míru trpělivosti a odříkání).
Klávesa Mezerník potom sloužila především k zobrazení aktuálního příběhu (jakéhosi deníčku postavy, resp. její vnitřní mluvy).
Stisk kláves
Samozřejmě u kláves R i Mezerník bylo potřeba ošetřit, aby jedno stisknutí nebylo vyhodnoceno vícekrát, protože jeden cyklus v MonoGame trvá třicetinu sekundy. Místo prstu by tedy musel hráč mít útočící kobru, aby stihl klávesu stisknout opravdu jen jednou.
Nabízí se možnost pamatovat si poslední klávesu, čímž je docíleno toho, že se žádná klávesa nevyhodnotí dvakrát po sobě. To ale nepřichází v úvahu tehdy, kdy chceme, aby bylo možné klávesu stisknout dvakrát po sobě.
Tehdy jsem jako nejjednodušší řešení shledal udělat proměnnou, která musí být na nule, aby bylo možné klávesu vyhodnotit jako stisknutou. Při každém stisknutí se přitom nastaví proměnná třeba na třicet. Od nenulové proměnné se pak v každém cyklu odečítá jedna.
Tím jsme vytvořili omezení na jednu klávesu za jednu sekundu.
Pohyb a jeho omezení
Postavička se samozřejmě nemůže pohybovat všude. Proto se při pohybu vždy vyhodnocuje, zda nenarazila na vertikální mantinely (příp. i horizontální, ty však většinou znamenají změnu místnosti). Pokročilejším řešením by bylo namapovat podlahu v každé místnosti zvlášť, ulehčil jsem si nicméně práci tím, že jsou mantinely všude stejné.
Vertikální pohyb má funkci čistě estetickou, resp. dodává hráči větší pocit svobody. Jinak žádnému účelu ve hře neslouží.
Vstup myší
Asi těžko by šlo o hru typu point-and-click bez myši. Proto jsem přidal vstup skrze myš. Základní myšlenka chození myší je ta, že po kliknutí se vytvoří jakýsi cíl chůze na zadaných souřadnicích a Eriugena půjde k tomuto cíli, dokud jej nedosáhne.
Pohyb k cíli
Prvním problémem byl diagonální pohyb, kdy by např. přibývalo/odečítalo se na osách X i Y zároveň. Aby byl rovnoměrný, musela by se de facto vypočítat přepona pravoúhlého trojúhelníku.
Proto jsem dal dva kroky. Eriugena nejprve "splní" chůzi:
- na ose X,
- potom teprve na ose Y.
Příchod do cíle
Další problém se týkal přesného příchodu do cíle. Ten měl dva podproblémy:
- cíl se nevymezuje přesně v místě kliknutí. To je totiž místo, kam chceme, aby postavička došla svýma nohama. Souřadnice postavičky (a jejího 2D spritu) jsou ale dány levým horním krajem obrázku. Musíme tedy přinejmenším přičíst na ose Y její výšku.
- při rychlosti vyšší než 1 pixel / cyklus častokrát nedojdeme do kliknutého bodu přesně. Postavička ho bude neustále přecházet z jedné či druhé strany, jak bude program neustále vyhodnocovat, že v cíli ještě nejsme. Proto musíme dát jistou toleranci, např. 20 bodů. A nezapomínat přitom zase, že vyhodnocujeme místo, kam dojde postavička svýma nohama.
Takhle nastavíme cíl chůze:
Mys_Cil_X = Ovladani_Mysi.X;
Mys_Cil_Y = Ovladani_Mysi.Y - 350;
A takhle, jestli jsme do něj došli:
if (((Mys_Cil_X + 20) > Eriugena_PoziceX && (Mys_Cil_X - 20) < Eriugena_PoziceX) && ((Mys_Cil_Y + 20) > Eriugena_PoziceY && (Mys_Cil_Y - 20) < Eriugena_PoziceY))
Klikání na NPC a předměty
Při kliknutí myší na NPC se spustím režim dialogu (podobný režimu příběhu), objeví se textura pergamenu a příslušný text.
Při kliknutí na předmět umístěný v dané místnosti
(na daných souřadnicích) se mu atribut JeVeSvete
změní na
false
a atribut JeVInventari
na true
. Pro
hru to znamená, že jej přestane vykreslovat ve světě a začne v
inventáři. A dále ho můžeme použít v rámci
děje (při čemž se může i "spotřebovat", tedy oba před chvílí
zmíněné atributy pak budou false
).
Jestli jsme klikli kupř. na předmět se vyhodnocuje následovně:
foreach (Predmety i in Predmety_List) { if (i.Mistnost == Eriugena_Mistnost && Ovladani_Mysi.X > i.PoziceX && Ovladani_Mysi.X < (i.PoziceX + i.Sirka) && Ovladani_Mysi.Y > i.PoziceY && Ovladani_Mysi.Y < (i.PoziceY + i.Vyska)) { i.JeVeSvete = false; i.JeVInventari = true; } }
Mimochodem, zrovna tady vidíme porušení zásady
zapouzdření. Správně se měly atributy měnit metodou ve třídě,
např.: i.Seber()
, která by pak uvnitř třídy
Predmety
měnila hodnoty oněch dvou atributů.
Vedla mě k tomu pohodlnost, která se u tak malého projektu nejspíše
nevymstí. Je dobré si to však připomínat.
Ne všechny předměty jsou hned na začátku ukázány v místnostech. Některé se objeví až v průběhu hry, aby nebylo možné je vysbírat hned na začátku. Kdyby se to tak ale dělalo s každým předmětem, ztratila by se možnost si jen tak syslit něco do inventáře.
Postup v příběhu
Postup v příběhu řeším skrze fáze. Ta je jednoduše
vyjádřena číslem typu int
, které si pak vyhodnotím pomocí
konstrukce switch
. Kdybych chtěl dát fázím jména, nabízel by
se také enum
, ale takto to bylo jednodušší.
U většího projektu by naopak bylo dobré přímo z názvu vidět, co se pod tím ukrývá. U čísel by si člověk musel vést jakýsi katalog).
Fáze
Použil jsem fáze dvojího typu. Fáze příběhu a fáze postavy.
Fáze příběhu
Fáze příběhu reprezentuje zejména vnitřní monolog Eriugeny, který si můžeme vyvolat klávesou Mezerník. Je to vlastně takový quest log, resp. připomenutí, co má hráč vlastně dělat.
Fáze postavy
Postavy mají své jednotlivé fáze. Když tedy např. promluvím s jednou postavou, může to posunout fázi dialogu u jiné postavy. Někdy si postava svou fázi posune i sama (třeba, když po nás chce předmět, který už ale máme v inventáři). V takovém případě je text posunující fáze de facto přeskočen (na což je třeba myslet při psaní textů, aby se hráč ve vyprávění neztratil).
Vizuální stránka hry
Zde popíšu to, co se v závislosti na logice hry objevuje na
obrazovce, tedy obsah metody Draw()
.
Falešný pixel-art
Dnes vzniká mnoho her a mnoho z nich je nesmírně graficky podmanivých. Přesto se domnívám, že jisté vizuální kouzlo, které měly ručně malované hry z např. 90. let, se už nevrátí (čest výjimkám, např. Heroine's Quest). Snad právě proto, že byly ručně malované. A možná i proto, že nepřesnost daná menším rozlišením více podněcovala fantazii hráče. A také proto, že jsme tehdy mnozí z nás byli mladší a nostalgie nasazuje všemu růžové brýle... Ale to je jiný příběh.
Podstatné je, že já nejsem zrovna výtvarník, ani jsem k tomu žádného neměl (nehledě na to, že jsem hru chtěl udělat rychle). Proto jsem udělal jakýsi falešný pixel-art tím, že jsem prostě zkombinoval, upravil a rozpixeloval obrázky z netu. Do určité míry jsem se tím vyhnul i právní stránce (přesto jsem se snažil, byla-li ta možnost, aby byly s licencí Creative Commons).
Trochu bizarní samozřejmě je, že různé prvky, které jsou najednou na obrazovce, mají různé rozlišení. Takovou možnost samozřejmě hry v 90. letech neměly. Musel jsem k tomu však sáhnout, protože kdyby např. některé postavy nebo malé předměty měly rozlišení jako třeba stěny za nimi, nebylo by prakticky nic rozpoznat. To samé platí např. o některých nápisech. Občas jsem přidal jakýsi "světelný" efekt, který spočívá v zásadě jen v masce výběru, ve které jsou lehce pozměněny barvy.
Vykreslení pozadí, postav a věcí
U vykreslení pozadí, postav, věcí a Eriugeny není příliš moc co rozebírat. Vykreslovaly se v tom pořadí, jaké je uvedeno před chvílí, aby byly ve správných vrstvách. Např. Eriugena je vždy před NPC, NPC jsou vždy před pozadím apod. Úplně navrchu jsou potom samozřejmě elementy UI: tj. popisky, inventář, příběhový pergamen apod.
Natočení a přešlapování Eriugeny
Zatímco na ostatní NPC stačí vždy jeden sprite (sice se přemisťují mezi svými místnostmi, ale jen v nepřítomnosti Eriugeny, jinak stojí na místě), tak na hlavní postavu jich je užito rovnou šest:
- Stání rovně
- Došlápnutí na levou nohu
- Došlápnutí na pravou nohu
To celé dvakrát s ohledem na varianty natočení vlevo/vpravo.
Tři varianty se v rámci jednoho natočení střídají při chůzi. To vyvolává sice trochu dojem tučňáka, působí to ale o něco méně strnule než výše již zmíněný neviditelný segway.
Dále, pro oživení postavy, jsem přidal metody, které otáčejí Eriugenou na strany a nutí jej přešlapovat v náhodných intervalech i tehdy, když se zrovna nehýbe. Je to prostě zvídavý neposeda.
Popisky v uživatelském rozhraní
Na herní obrazovce je i několik popisků. Ty jediné
nejsou rozpixelované, ale jedná se o normální vykreslení fontu pomocí
_spriteBatch.DrawString()
. Byl to ústupek tomu, aby se daly
dobře číst, a rovněž to takto bylo jednodušší. Jinak by
každý jediný řádek textu ve hře musel být obrázkem.
Každá postava má zadanou ve hře svou
barvu pro rozlišení v dialozích. Vypravěč má
barvu Color.Silver
a herní tipy skrze různé jiné barvy.
Barvy UI se mění v závislosti na tom,
jestli je hráč v režimu chození, nebo
příběhu.
Závěr
Pro dokreslení atmosféry jsem použil ve hře jednu royalty free skladbu z YouTube. V této hře jsem si žánr adventury spíše jen ohmatával a možná v budoucnu ještě něco takového vytvořím.
Přikládám ke stažení release složky i s EXE souborem,
zde jsou potom odkazy na kompletní zdrojové kódy (musel jsem
ten pro třídu Eriugena.cs
rozdělit do dvou kvůli omezení na
délku zdrojáku):
- Eriugena.cs - hlavní třída, ve které se
odehrává hra (I. část kódu),
- Eriugena.cs - hlavní třída, ve které se
odehrává hra (II. část kódu),
- Predmety.cs - třída pro evidenci
předmětů,
- Npcka.cs - třída pro evidenci NPC.
Galerie
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 6x (52.29 MB)
Aplikace je včetně zdrojových kódů v jazyce C#