IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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ů):

Plánek - Zdrojákoviště C# .NET - XNA a MonoGame

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.

Eriugena s opatem - Zdrojákoviště C# .NET - XNA a MonoGame

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))
Eriugena ve skriptoriu - Zdrojákoviště C# .NET - XNA a MonoGame

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).

Dialog ve hře - Zdrojákoviště C# .NET - XNA a MonoGame

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.

Eriugena s žíznivým mnichem - Zdrojákoviště C# .NET - XNA a MonoGame

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:

  1. Stání rovně
  2. Došlápnutí na levou nohu
  3. 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.

Eriugena v temném lese - Zdrojákoviště C# .NET - XNA a MonoGame

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

Hra byla vytvořena v roce 2022.

 

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#

 

Všechny články v sekci
Zdrojákoviště C# .NET - XNA a MonoGame
Článek pro vás napsal Jakub Raida
Avatar
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Autor má rád literaturu, dějiny, filmy, počítačové hry, paleontologii, vesmír a programování.
Aktivity