Semestrální práce z předmětu X36TJC:

Krtek

Josef Kufner <kufnej1@fel.cvut.cz>
zimní semestr 2005/2006

Ze začátku bylo cílem napsat hru ovládanou zvukem. Co bude tématem hry velmi dlouho nebylo známo, a proto jsem začal psát hru co nejobecněji. Základním požadavkem bylo maximálně oddělit od sebe to, co oddělit jde a proto jsem program rozdělil na několik hlavních tříd: Game, Sample, Screen a GameWorld.

Po zkušenosti s dřívější semestrální prací jsem se rozhodl využít vláken a napsal jsem třídu Thread. Uchvácen jednoduchostí s jakou jsem mohl tvořit další vlákna, jsem nechal každou z hlavních částí programu běžet ve vlastním vláknu, což se později ukázalo jako naprosto nevhodné.

Nakonec zbyla vlákna jen dvě: první, používající třídy Game a Screen, a druhé, používající třídu Sample. Tyto dvě vlákna spolu komunikují pomocí roury, kterou Sample posílá pointery na instance třídy SampleMsg. Toto se naopak ukázalo jeko celkem šikovný a jednoduchý způsob komunikace.

Struktura programu

[schéma struktury programu]

Hiearchie tříd hracího světa

Poznámka: Tento obrázek je vygenerovaný Doxygenem.

Spolupráce jednotlivých objektů v hracím světě

Každý objekt v hracím světě, i svět sám, je potomkem třídy GObject. Díky tomu každá instance třídy ví, kde je v nadřazeném objektu umístěna, co je její nadřazený objekt a jaké další objekty obsahuje. Tohoto plně využívá pouze GameWorld, ale pro zjednoduššení manipulace s objekty a pointery na ně, mají tyto schopnosti všechny objekty.

Aby bylo možné lehce nastavovat jakémukoliv objektu jakékoliv vlastnosti, nejen ty zděděné od GObject, je v GObject implementováno rozhraní, pomocí kterého si každý objekt zaregistruje vlastnosti, které chce zpřístupnit a kterýkoliv jiný objekt má k těmto vlastnostem přístup. Toto je řešeno pomocí multimapu obsahujícího id vlastnosti a pointer na proměnnou v konkrétní instanci třídy. Při implementaci tohoto rozhraní jsem počítal s tím, že některé vlastnosti budou read-only, ale tuto funkčnost jsem nepotřeboval, takže při registrování vlastnosti je tento parametr ignorován. Pokud by se naskytla nutnost použít vlastnost jiného typu než je int, tak stačí napsat zapouzdřující třídu a upravit jeden typedef v současné implementaci.

Kompilace a použité knihovny

Pro překlad programu je využíváno služeb obvyklého GNU Make a pravidel popsaných v makefile. Tj. stačí "make". Soubor makefile je generován skriptem mfgen.

V programu jsou použity standardní knihovny jazyka C++ a ncurses. Snímání zvuku je závislé na operačním systému. Hra byla napsána na Linuxu, ale vzhledem k tomu že kód týkající se čtení zvuku je převzat z programu wmscope, tak je možné, že to bude fungovat i na FreeBSD a Solarisu. Na převod zvukových dat na frekvenční spektrum byl použit kód z programu XMMS – soubory fft.cc a fft.h, ve kterých bylo provedeno jen minimum úprav. Vzhledem k licenci převzatého kódu je i tato hra šířena pod licencí GNU General Public Licence.

Nastavení zvuku podle použitého operačního systému

Na začátku souboru makefile, na řádku začínajícím CFLAGS= zaměň -DSOUND_OSS za:

Testováno jen na Linuxu. Spuštění mfgen toto nastavení zachovává.

Hra z pohledu hráče

O co jde?

Krtek je jednoduchá 2D honička. Zahradník sází kytičky, krtek mu je ničí a rozhrabává zahradu. Za každou vykvetlou kytičku (zavináč) dostane zahradník bod, krtek dostane za každou zničenou bodů pět. Aby to nebylo moc nudné, tak se každý pohybuje jinak rychle. Zahradník běhá svižně po travičce, pomalu po rozhrabané hlíně, kterou po cestě urovnává. Krtek se pohybuje po trávě trochu pomaleji než zahradník, protože ji rozrývá, ale po rozryté trávě se pohybuje opravdu velmi rychle, což mu umožňuje provádět efektní úniky před zahradníkem.

Aby zahradník měl motivaci honit krtka, je na krtka vypsána odměna 20 bodů, které jsou zahradníkovi přiděleny pokud se ocitne na stejném políčku jako krtek. To by ovšem bylo moc lehké a proto je v návrhu algoritmu na detekci kolizí chyba, která poněkud ztěžuje podmínky pro „chycení“ krtka.

Jako malé zpestření není v hracím světě jen tráva, ale i voda. Vzhledem k tomu, že ani krtek, ani zahradník neumí plavat, tak je voda naprosto neprostupnou překážkou. Jak je vidět v hiearchii tříd hracího světa, v budoucnu se možná dočkáme dalších typů povrchu a věcí poházených po travičce.

Ovládání

Každý hráč ovládá svojí postavičku dvojicí tónů. Jeden znamená „doleva“ a druhý „doprava“. Hra je nastavena tak, že krtek má ovládání na nízkých frekvencích, tak akorát na podivné hučení. Zahradník by měl umět pískat, protože je jeho ovládání na poněkud vyšších frekvencích. Na délce tónu nezáleží – bere se začátek.

Aby hráči viděli do jakých frekvencí se mají trefit, je pod hrací plochou zobrazeno frekvenční spektrum snímaného zvuku. Pod ním je písmeny 'k', 'K', 'z' a 'Z' vyznačeny jednotlivá pásma. Na stejném řádku je také vyobrazena intenzita snímaného signálu, která musí dosahovat zelených hodnot, aby byl signál interpretován.

Cíl hry

Nasbírat co nejvíc bodů. Hra běží do té doby, dokud nespadne. Předčasného ukončení lze dosáhnout zasláním signálu SIGTERM (Ctrl+C), pokud nestačí jednou, tak má smysl to zkoušet i podruhé, ale potřetí doporučuji raději použít SIGKILL.

Josef Kufner