Dnes to všechno — třídy, grafiku, seznamy a tak dále – spojíme dohromady do závěrečného projektu. Doufám, že se ti bude líbit!
Naším cílem bude vytvořit klon známé hry Snake (neboli Had) jejíž princip je tu s námi od roku 1976. Největší popularity se Had dočkal díky mobilním telefonům Nokia, kde je jako základní hra dostupný od roku 1998 až dodnes.
Projekt není zase tak složitý, protože jeho základní principy už dobře znáš z domácích projektů a lekcí kurzu. Následující text je tedy spíše zadání než výukový materiál a v projektu jistě narazíš na něco, co jsme společně neprobírali. V takovém případě se neboj zeptat nebo si informace dohledat!
A ještě jedna věc: protože začátečnický kurz končí, začneme kód psát v angličtině, aby se pak dal sdílet s celým světem.
Procházíš-li si projekt doma, je možné, že narazíš na něco s čím si nebudeš vědět rady. Kdyby se to stalo, prosím, ozvi se nám! Rádi ti s projektem pomůžeme.
Základní princip hry máš v malíčku, pokud jsi dokončila domácí projekt po lekci o seznamech. Pokud jej nemáš, doporučuji se k němu vrátit.
Práci s pygletem jsme dělali v lekci o grafice.
Teď nám nezbývá než princip tolik populární hry a znalosti z kurzu spojit dohromady. Doporučuji začít s čistým souborem v prázdné složce a do hotových programů se koukat jen v případě potřeby.
Jak postupovat, aby se projekt nezdál nedosažitelný už na začátku? Třeba takto:
Po těchto krocích budeš mít základní hru, ale tou to nekončí, právě naopak! Budeš mít vlastní hru, jejímuž fungování rozumíš jako nikdo jiný, a to je to pravé pro přidávání dalších možností. Fantazii se meze nekladou. Například:
V příkazové řádce měl had souřadnice označující řádek a sloupec. V grafické aplikaci to bude podobné, ale protože pixelů na obrazovce je mnohem více, budeme si muset vytvořit pomyslnou síť stejně velkých čtverců, které nám nahradí řádky a sloupce. Velikost takového čtverce bude konstanta, kterou se vyplatí mít po celou dobu hry k dispozici, aby se podle ní daly vypočítat souřadnice k vykreslení obrázků. Pro začátek řekněme, že ideální velikost takového čtverce bude 64 × 64 pixelů.
Z velikosti čtverce, kterou si můžeme v budoucnu libovolně změnit, a velikosti okna aplikace můžeme vypočítat, kolik se nám do okna takových čtverců vejde na šířku a na výšku a tím i zjistit, kolik pomyslných sloupců a řádků bude naše hrací plocha mít.
Abychom mohli hada vykreslit, potřebujeme si pro začátek uložit jeho souřadnice. K tomu můžeš použít seznam dvojic – stejně jako v domácím projektu. Podobných informací, které se budou v průběhu hry dynamicky měnit, budeme mít už za malou chvíli více. Proto dává smysl si pro stav hry vytvořit třídu, která bude tyto informace obsahovat jako atributy a bude s nimi umět pracovat.
I když se může na začátku zdát vlastní třída jako zbytečná komplikace, později zjistíš, že ne všechno by se dalo snadno udržovat v globálních proměnných.
Když už je had definován, budeme potřebovat jednoduchou funkci, která na ta správná místa umístí obrázky. Pro začátek si vystačíme se zeleným čtvercem. Obrázek si stáhni zde a ulož do složky k programu.
Stejně jako na lekci i zde použijeme pro vykreslení Sprite
, kterému už při
vytvoření můžeme zadat obrázek pro vykreslení a vypočtené souřadnice.
Pro jednoduchost stačí Sprite
vytvořit, vykreslit a „zapomenout“. Není to ale
optimální přístup a tak tohle může být jedním z adeptů pro pozdější vylepšení.
Aby se mohl had hýbat, potřebuje znát směr pohybu. V příkazové řádce jsme vždy počkali, až nám směr zadá uživatel, ale v opravdové hře se bude had pohybovat sám. Bude tedy potřeba nějaký atribut v naší třídě, kde bude směr neustále uložen a měnit se bude podle stisknutých kláves v dalším kroku.
Směr pohybu může být uložen v libovolné podobě – světové strany, slovní
označení strany, nebo třeba dvojice s číselným označením pohybu
((0, 1)
pro pohyb nahoru, (-1, 0)
pro pohyb doleva atp.). Podle vybraného
formátu pak bude třeba směr zpracovat.
Pro tuhle chvíli mu tedy bude stačit nastavit směr napevno a napsat funkci, nebo metodu, která hadem pohne. Pohyb bude probíhat naprosto stejně jako v příkazové řádce – přidáme do seznamu souřadnice, kde by měla být „nová hlava“ a umažeme poslední kousek hada.
Protože se pohyb má provádět pravidelně, bude potřeba tuto operaci provádět
automaticky v pravidelných intervalech. pyglet.clock.schedule_interval
je
zde jasná volba.
Reagovat na stisknuté klávesy jsme se už taky učili. Teď to tedy využijeme, abychom dokázali změnit nastavený směr pohybu z předchozího bodu. Bude pro to samozřejmě potřeba funkce, kterou v pygletu zaregistrujeme pro spuštění po stisku klávesy.
Protože had už se nám v závislosti na směru pohybuje, měl by začít reagovat na jeho změnu.
V tuto chvíli:
Vida, máme hotový základ!
Had už se nám hýbe podle našich představ, ale stačí ho nechat chvíli bez dozoru a uteče nám z hrací plochy. Tomu není těžké zabránit, když víme, že žádná souřadnice hada nesmí být menší než nula a větší než je velikost hrací plochy. Kontrolovat je potřeba souřadnice jeho hlavy, která bude vždy všude jako první.
Reagovat na náraz do zdi se dá mnoha způsoby. Nejjednodušší by asi bylo ukončit hru, ale to by se pak hráč nemohl podívat na tu šlamastiku, do které se dostal. Proto bude lepší místo toho pouze zastavit časovač, který se stará o pohyb hada.
Stejným způsobem a na stejném místě v programu bude třeba vyřešit i situaci, kdy had narazí sám do sebe.
Jezdit s hadem po hrací ploše může být chvíli zábava, ale protože had neroste, není to žádná výzva. A aby mohl růst, potřebuje jíst.
K tomu budeš potřebovat další globálně dostupný seznam (nejlépe atribut existující třídy), který bude obsahovat informace (souřadnice) o existujícím jídle na hrací ploše. Navíc bude potřeba mít k dispozici metodu, která bude umět jídlo na hrací plochu přidat.
Záleží jen na tobě, zda se bude nové jídlo objevovat, když had jedno z existujících sní, nebo automaticky v pravidelných intervalech.
Jídlo vykreslíme stejným způsobem jako hada (ve stejné funkci/metodě) a jako obrázek použijeme třeba jablko.
První závan grafiky :-)
Čtverečky jsou fajn, ale hra by měla lahodit oku a had by měl vypadat jako had.
K tomu máme připravenou sadu obrázků - ke stažení zde.
Archiv si rozbal do adresáře s hrou tak, aby adresář snake-tiles
byl na stejné
úrovni jako soubor s programem.
Nejdříve si načteme všechny obrázky do hry, abychom je pak mohli bez potíží
použít. Protože se nechceme opakovat (DRY), bude potřeba to udělat nějak
poloautomaticky. Python obsahuje knihovnu pathlib
,
která umí velmi přehledně pracovat s cestami k souborům a třeba nám dát
i seznam všech souborů ve složce.
Nejdříve si z této knihovny naimportujeme třídu Path
, která reprezentuje
soubor či složku na disku a vytvoříme z ní instanci, která bude
ukazovat do naší složky s obrázky.
from pathlib import Path
TILES_DIRECTORY = Path('snake-tiles')
Třída Path
má metodu glob()
, která nám ze zadané cesty umí vrátit sekvenci
s názvy souborů dle argumentem zadaných kritérií. My potřebujeme všechny soubory
s příponou .png
bez ohledu na jméno. Jakýkoli řetězec je v regulárních
výrazech označen hvězdičkou (*
), takže argument pro metodu glob()
bude
*.png
, což označuje jakýkoli soubor s příponou .png
. Jako výsledek
dostaneme sekvenci cest k souborům s obrázky, kterou můžeme projít pomocí cyklu
for
, a každý obrázek si můžeme načíst do slovníku, kde hodnotou bude samotný obrázek
pyglet.image
a klíčem jeho název. Z názvu však potřebujeme jen samotný název souboru
bez přípony a názvu složky – ten je uložen v atributu stem
.
Výsledný slovník by měl vypadat takto:
{'right-tongue': <ImageData 64x64>, 'top-tongue': <ImageData 64x64>,
'right-top': <ImageData 64x64>, 'left-bottom': <ImageData 64x64>,
'tail-left': <ImageData 64x64>, 'bottom-tongue': <ImageData 64x64>,
'left-top': <ImageData 64x64>, 'bottom-bottom': <ImageData 64x64>,
...
Pokud je tohle pro tebe příliš mnoho nových věcí najednou a nedaří se ti to vyřešit, zkus to ještě jednou a pak se můžeš podívat na řešení.
Než se začneme zabývat různými obrázky, uděláme pokus k ověření, že nám vše stále funguje.
Jako mezistupeň od hranatého hada k jeho věrné grafické podobě vytvoř housenku.
Uděláš to jednoduše tak, že místo zeleného čtverce použiješ k vykreslení hada
obrázek tail-head.png
, který máš ve slovníku načten jako pod klíčem tail-head
.
Funguje? No výborně! Před pokračováním si u jeho hraní na chvíli odpočiň. Začne to být náročnější.
Jistě sis všimla, že některé obrázky v naší sadě jsou téměř identické a liší se jen v otočení. V tuhle chvíli máme totiž dvě možnosti, jak vykreslit celého hada pomocí správných obrázků na správných pozicích:
Bod č. 2 je v tuto chvíli snazší a tak budeme pokračovat tímto způsobem.
Jak vybrat správné obrázky na ta správná místa? Jména obrázků (klíče ve slovníku) obsahují informaci, odkud kam daný obrázek vede. Stačí se tedy při vykreslování každého kousku hada podívat na umístění jednoho před ním a jednoho za ním a podle toho vybrat ze slovníku ten správný obrázek. U každého kousku hada a kousku před i za ním tě budou zajímat jejich souřadnice, protože podle nich lze velmi snadno poznat, zda je zkoumaný kousek nalevo, napravo, nahoře, nebo dole.
Způsobů, jak toho docílit, je celá řada a i když se to může zdát jako složitější úkol, vše potřebné k jeho vyřešení znáš.
Odměnou za vyřešení ti bude kompletní grafická hra Had. Gratuluji!
Než se po dokončení základní hry vrhneš na její rozšiřování, měl by se celý kód uklidit a zpřehlednit, aby se v něm další úpravy dělaly snáze a s menším rizikem, že se něco pokazí.
Body k zamyšlení:
Sprite
a ten
je po vykreslení zapomenut. Optimálnější by možná bylo použít seznam
a v něm všechny instance třídy Sprite
uchovávat a používat znovu a znovu.
Sprite
přeci můžeme posunout na libovolné místo i změnit obrázek, který
obsahuje.{ "data": { "sessionMaterial": { "id": "session-material:2018/pyladies-ostrava-podzim:asteroids:1", "title": "Snake", "html": "\n \n \n\n <h1>Hra typu Had</h1>\n<p>Dnes to všechno — třídy, grafiku, seznamy a tak dále –\nspojíme dohromady do závěrečného projektu.\nDoufám, že se ti bude líbit!</p>\n<p>Naším cílem bude vytvořit klon známé hry <a href=\"https://en.wikipedia.org/wiki/Snake_(video_game_genre)\">Snake (neboli Had)</a>\njejíž princip je tu s námi od roku 1976. Největší popularity se Had dočkal\ndíky mobilním telefonům Nokia, kde je jako základní hra dostupný od roku 1998\naž dodnes.</p>\n<p>Projekt není zase tak složitý, protože jeho základní principy už dobře znáš\nz domácích projektů a lekcí kurzu. Následující text je tedy spíše\nzadání než výukový materiál a v projektu jistě narazíš na něco, co jsme\nspolečně neprobírali. V takovém případě se neboj zeptat nebo si informace\ndohledat!</p>\n<p>A ještě jedna věc: protože začátečnický kurz končí,\nzačneme kód psát v angličtině, aby se pak dal sdílet s celým světem.</p>\n<div class=\"admonition note\"><p>Procházíš-li si projekt doma, je možné, že narazíš na\nněco s čím si nebudeš vědět rady.\nKdyby se to stalo, prosím, ozvi se nám!\nRádi ti s projektem pomůžeme.</p>\n</div><h2>Logika hry a fáze projektu</h2>\n<p>Základní princip hry máš v malíčku, pokud jsi dokončila domácí projekt\npo <a href=\"/2018/pyladies-ostrava-podzim/beginners/list/\">lekci o seznamech</a>. Pokud jej nemáš, doporučuji\nse k němu vrátit.</p>\n<p>Práci s pygletem jsme dělali v <a href=\"/2018/pyladies-ostrava-podzim/intro/pyglet/\">lekci o grafice</a>.</p>\n<p>Teď nám nezbývá než princip tolik populární hry a znalosti z kurzu spojit\ndohromady. Doporučuji začít s čistým souborem v prázdné složce a do hotových\nprogramů se koukat jen v případě potřeby.</p>\n<p>Jak postupovat, aby se projekt nezdál nedosažitelný už na začátku? Třeba takto:</p>\n<ol>\n<li>Promysli si, jak bude hra fungovat a jak přeneseme mřížku s hadem\nz příkazové řádky do grafického okna.</li>\n<li>Vykresli hada do grafického okna (ve formě barevných čtverců)</li>\n<li>Přidej funkci, která bude hadem hýbat.</li>\n<li>Umožni změnit směr hada pomocí klávesnice.</li>\n<li>Nenech hada utéct z herní plochy a nabourat do sebe sama.</li>\n<li>Přidej hadovi jídlo a zajisti, aby po jídle rostl.</li>\n<li>Vyměň barevné čtverečky za opravdovou grafiku.</li>\n</ol>\n<p>Po těchto krocích budeš mít základní hru, ale tou to nekončí, právě naopak!\nBudeš mít vlastní hru, jejímuž fungování rozumíš jako nikdo jiný, a to je to pravé pro\npřidávání dalších možností. Fantazii se meze nekladou. Například:</p>\n<ol>\n<li>Ve hře mohou být dva nebo třeba tři hadi najednou – každý ovládaný\njinými klávesami — navzájem soupeřící o jídlo.</li>\n<li>Kromě jídla se mohou na ploše objevovat i jiné objekty – překážky,\ndo kterých nesmí had narazit, otrávené jídlo, které hada zkrátí atp.</li>\n<li>Hrací plocha může být nekonečná a když z ní had vyleze, objeví se\nna druhé straně.</li>\n</ol>\n<h2>Z příkazové řádky do grafické aplikace</h2>\n<p>V příkazové řádce měl had souřadnice označující řádek a sloupec. V grafické\naplikaci to bude podobné, ale protože pixelů na obrazovce je mnohem více, budeme\nsi muset vytvořit pomyslnou síť stejně velkých čtverců, které nám nahradí\nřádky a sloupce. Velikost takového čtverce bude konstanta, kterou se vyplatí\nmít po celou dobu hry k dispozici, aby se podle ní daly vypočítat\nsouřadnice k vykreslení obrázků. Pro začátek řekněme, že ideální velikost\ntakového čtverce bude 64 × 64 pixelů.</p>\n<p>Z velikosti čtverce, kterou si můžeme v budoucnu libovolně změnit,\na velikosti okna aplikace můžeme vypočítat, kolik se nám do okna takových\nčtverců vejde na šířku a na výšku a tím i zjistit, kolik pomyslných\nsloupců a řádků bude naše hrací plocha mít.</p>\n<h2>Vykreslení hada</h2>\n<p>Abychom mohli hada vykreslit, potřebujeme si pro začátek uložit jeho souřadnice.\nK tomu můžeš použít seznam dvojic – stejně jako v domácím projektu. Podobných\ninformací, které se budou v průběhu hry dynamicky měnit, budeme mít už\nza malou chvíli více. Proto dává smysl si pro stav hry vytvořit třídu, která\nbude tyto informace obsahovat jako atributy a bude s nimi umět pracovat.</p>\n<div class=\"admonition note\"><p>I když se může na začátku zdát vlastní třída jako zbytečná\nkomplikace, později zjistíš, že ne všechno by se dalo snadno udržovat v globálních\nproměnných.</p>\n</div><p><span class=\"figure\"><a href=\"/2018/pyladies-ostrava-podzim/projects/snake/static/coords.svg\"><img src=\"/2018/pyladies-ostrava-podzim/projects/snake/static/coords.svg\" alt=\"Had na „šachovnici“ se souřadnicemi\"></a></span></p>\n<p>Když už je had definován, budeme potřebovat jednoduchou funkci, která\nna ta správná místa umístí obrázky. Pro začátek si vystačíme se zeleným\nčtvercem. Obrázek si <a href=\"/2018/pyladies-ostrava-podzim/projects/snake/static/green.png\">stáhni zde</a> a ulož\ndo složky k programu.</p>\n<p>Stejně jako na lekci i zde použijeme pro vykreslení <code>Sprite</code>, kterému už při\nvytvoření můžeme zadat obrázek pro vykreslení a vypočtené souřadnice.\nPro jednoduchost stačí <code>Sprite</code> vytvořit, vykreslit a „zapomenout“. Není to ale\noptimální přístup a tak tohle může být jedním z adeptů pro pozdější vylepšení.</p>\n<h2>Rozpohybování hada</h2>\n<p>Aby se mohl had hýbat, potřebuje znát směr pohybu. V příkazové řádce jsme\nvždy počkali, až nám směr zadá uživatel, ale v opravdové hře se bude had\npohybovat sám. Bude tedy potřeba nějaký atribut v naší třídě, kde bude směr\nneustále uložen a měnit se bude podle stisknutých kláves v dalším kroku.</p>\n<p>Směr pohybu může být uložen v libovolné podobě – světové strany, slovní\noznačení strany, nebo třeba dvojice s číselným označením pohybu\n(<code>(0, 1)</code> pro pohyb nahoru, <code>(-1, 0)</code> pro pohyb doleva atp.). Podle vybraného\nformátu pak bude třeba směr zpracovat.</p>\n<p>Pro tuhle chvíli mu tedy bude stačit nastavit směr napevno a napsat funkci,\nnebo metodu, která hadem pohne. Pohyb bude probíhat\nnaprosto stejně jako v příkazové řádce – přidáme do seznamu souřadnice,\nkde by měla být „nová hlava“ a umažeme poslední kousek hada.</p>\n<p>Protože se pohyb má provádět pravidelně, bude potřeba tuto operaci provádět\nautomaticky v pravidelných intervalech. <code>pyglet.clock.schedule_interval</code> je\nzde jasná volba.</p>\n<h2>Ovládání pomocí klávesnice</h2>\n<p>Reagovat na stisknuté klávesy jsme se už taky učili. Teď to tedy využijeme,\nabychom dokázali změnit nastavený směr pohybu z předchozího bodu. Bude pro to\nsamozřejmě potřeba funkce, kterou v pygletu zaregistrujeme pro spuštění po\nstisku klávesy.</p>\n<p>Protože had už se nám v závislosti na směru pohybuje, měl by začít reagovat\nna jeho změnu.</p>\n<p>V tuto chvíli:</p>\n<ul>\n<li>Směr se mění podle stisknuté klávesy.</li>\n<li>Had se sám pohybuje podle zadaného směru.</li>\n<li>Nová pozice hada se automaticky vykresluje jako zelené čtverečky.</li>\n</ul>\n<p>Vida, máme hotový základ!</p>\n<h2>Nenechme ho utéct</h2>\n<p>Had už se nám hýbe podle našich představ, ale stačí ho nechat chvíli bez dozoru\na uteče nám z hrací plochy. Tomu není těžké zabránit, když víme, že žádná\nsouřadnice hada nesmí být menší než nula a větší než je velikost hrací plochy.\nKontrolovat je potřeba souřadnice jeho hlavy, která bude vždy všude jako první.</p>\n<p>Reagovat na náraz do zdi se dá mnoha způsoby. Nejjednodušší by asi bylo\nukončit hru, ale to by se pak hráč nemohl podívat na tu šlamastiku, do které\nse dostal. Proto bude lepší místo toho pouze zastavit časovač, který se stará\no pohyb hada.</p>\n<p>Stejným způsobem a na stejném místě v programu bude třeba vyřešit i situaci,\nkdy had narazí sám do sebe.</p>\n<h2>Jen ať jí, hlavně že mu chutná</h2>\n<p>Jezdit s hadem po hrací ploše může být chvíli zábava, ale protože had neroste,\nnení to žádná výzva. A aby mohl růst, potřebuje jíst.</p>\n<p>K tomu budeš potřebovat další globálně dostupný seznam (nejlépe atribut\nexistující třídy), který bude obsahovat informace (souřadnice) o existujícím\njídle na hrací ploše. Navíc bude potřeba mít k dispozici metodu, která bude\numět jídlo na hrací plochu přidat.</p>\n<p>Záleží jen na tobě, zda se bude nové jídlo objevovat, když had jedno\nz existujících sní, nebo automaticky v pravidelných intervalech.</p>\n<p>Jídlo vykreslíme stejným způsobem jako hada (ve stejné funkci/metodě) a jako\nobrázek použijeme třeba <a href=\"/2018/pyladies-ostrava-podzim/projects/snake/static/apple.png\">jablko</a>.</p>\n<p>První závan grafiky :-)</p>\n<h2>Čtverečky ven, grafiku sem</h2>\n<p>Čtverečky jsou fajn, ale hra by měla lahodit oku a had by měl vypadat jako had.\nK tomu máme připravenou sadu obrázků - <a href=\"/2018/pyladies-ostrava-podzim/projects/snake/static/snake-tiles.zip\">ke stažení zde</a>.\nArchiv si rozbal do adresáře s hrou tak, aby adresář <code>snake-tiles</code> byl na stejné\núrovni jako soubor s programem.</p>\n<p><span class=\"figure\"><a href=\"/2018/pyladies-ostrava-podzim/projects/snake/static/snake-tiles.png\"><img src=\"/2018/pyladies-ostrava-podzim/projects/snake/static/snake-tiles.png\" alt=\"Kousky hada\"></a></span></p>\n<h3>Načtení všech obrázků ze složky</h3>\n<p>Nejdříve si načteme všechny obrázky do hry, abychom je pak mohli bez potíží\npoužít. Protože se nechceme opakovat (DRY), bude potřeba to udělat nějak\npoloautomaticky. Python obsahuje knihovnu <a href=\"https://docs.python.org/3/library/pathlib.html\"><code>pathlib</code></a>,\nkterá umí velmi přehledně pracovat s cestami k souborům a třeba nám dát\ni seznam všech souborů ve složce.</p>\n<p>Nejdříve si z této knihovny naimportujeme třídu <code>Path</code>, která reprezentuje\nsoubor či složku na disku a vytvoříme z ní instanci, která bude\nukazovat do naší složky s obrázky.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">pathlib</span> <span class=\"kn\">import</span> <span class=\"n\">Path</span>\n\n<span class=\"n\">TILES_DIRECTORY</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'snake-tiles'</span><span class=\"p\">)</span>\n</pre></div><p>Třída <code>Path</code> má metodu <code>glob()</code>, která nám ze zadané cesty umí vrátit sekvenci\ns názvy souborů dle argumentem zadaných kritérií. My potřebujeme všechny soubory\ns příponou <code>.png</code> bez ohledu na jméno. Jakýkoli řetězec je v regulárních\nvýrazech označen hvězdičkou (<code>*</code>), takže argument pro metodu <code>glob()</code> bude\n<code>*.png</code>, což označuje jakýkoli soubor s příponou <code>.png</code>. Jako výsledek\ndostaneme sekvenci cest k souborům s obrázky, kterou můžeme projít pomocí cyklu\n<code>for</code>, a každý obrázek si můžeme načíst do slovníku, kde hodnotou bude samotný obrázek\n<code>pyglet.image</code> a klíčem jeho název. Z názvu však potřebujeme jen samotný název souboru\nbez přípony a názvu složky – ten je uložen v atributu <code>stem</code>.</p>\n<p>Výsledný slovník by měl vypadat takto:</p>\n<div class=\"highlight\"><pre><code>{'right-tongue': <ImageData 64x64>, 'top-tongue': <ImageData 64x64>,\n 'right-top': <ImageData 64x64>, 'left-bottom': <ImageData 64x64>,\n 'tail-left': <ImageData 64x64>, 'bottom-tongue': <ImageData 64x64>,\n 'left-top': <ImageData 64x64>, 'bottom-bottom': <ImageData 64x64>,\n ...</code></pre></div><p>Pokud je tohle pro tebe příliš mnoho nových věcí najednou a nedaří se ti to\nvyřešit, zkus to ještě jednou a pak se můžeš podívat na řešení.</p>\n<div class=\"solution\" id=\"solution-0\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2018/pyladies-ostrava-podzim/projects/snake/index/solutions/0/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">pathlib</span> <span class=\"kn\">import</span> <span class=\"n\">Path</span>\n\n<span class=\"kn\">import</span> <span class=\"nn\">pyglet</span>\n\n<span class=\"n\">TILES_DIRECTORY</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'snake-tiles'</span><span class=\"p\">)</span>\n\n<span class=\"n\">snake_tiles</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n<span class=\"k\">for</span> <span class=\"n\">path</span> <span class=\"ow\">in</span> <span class=\"n\">TILES_DIRECTORY</span><span class=\"o\">.</span><span class=\"n\">glob</span><span class=\"p\">(</span><span class=\"s1\">'*.png'</span><span class=\"p\">):</span>\n <span class=\"n\">snake_tiles</span><span class=\"p\">[</span><span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">stem</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">image</span><span class=\"o\">.</span><span class=\"n\">load</span><span class=\"p\">(</span><span class=\"n\">path</span><span class=\"p\">)</span>\n\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">snake_tiles</span><span class=\"p\">)</span>\n</pre></div>\n </div>\n</div><h3>Housenka</h3>\n<p>Než se začneme zabývat různými obrázky, uděláme pokus k ověření, že nám vše stále funguje.\nJako mezistupeň od hranatého hada k jeho věrné grafické podobě vytvoř housenku.\nUděláš to jednoduše tak, že místo zeleného čtverce použiješ k vykreslení hada\nobrázek <code>tail-head.png</code>, který máš ve slovníku načten jako pod klíčem <code>tail-head</code>.</p>\n<p>Funguje? No výborně! Před pokračováním si u jeho hraní na chvíli odpočiň.\nZačne to být náročnější.</p>\n<p><span class=\"figure\"><a href=\"/2018/pyladies-ostrava-podzim/projects/snake/static/screenshot-cat.png\"><img src=\"/2018/pyladies-ostrava-podzim/projects/snake/static/screenshot-cat.png\" alt=\"Housenka\"></a></span></p>\n<h3>Výběr správných obrázků</h3>\n<p>Jistě sis všimla, že některé obrázky v naší sadě jsou téměř identické a liší\nse jen v otočení. V tuhle chvíli máme totiž dvě možnosti, jak vykreslit\ncelého hada pomocí správných obrázků na správných pozicích:</p>\n<ol>\n<li>Můžeme vzít jeden obrázek pro tělo, jeden pro ohyb a po jednom pro\nhlavu a ocas a ty otáčet tak, jak to bude pro konkrétní kousek hada potřeba.</li>\n<li>Můžeme využít všech dostupných (různé otočených) obrázků a použít ten\nsprávný obrázek na tom správném místě.</li>\n</ol>\n<p>Bod č. 2 je v tuto chvíli snazší a tak budeme pokračovat tímto způsobem.</p>\n<p>Jak vybrat správné obrázky na ta správná místa? Jména obrázků (klíče ve slovníku)\nobsahují informaci, odkud kam daný obrázek vede. Stačí se tedy při\nvykreslování každého kousku hada podívat na umístění jednoho před ním\na jednoho za ním a podle toho vybrat ze slovníku ten správný obrázek.\nU každého kousku hada a kousku před i za ním tě budou zajímat jejich\nsouřadnice, protože podle nich lze velmi snadno poznat, zda je zkoumaný kousek\nnalevo, napravo, nahoře, nebo dole.</p>\n<p>Způsobů, jak toho docílit, je celá řada a i když se to může zdát jako složitější\núkol, vše potřebné k jeho vyřešení znáš.</p>\n<p><span class=\"figure\"><a href=\"/2018/pyladies-ostrava-podzim/projects/snake/static/screenshot-final.png\"><img src=\"/2018/pyladies-ostrava-podzim/projects/snake/static/screenshot-final.png\" alt=\"Finální had\"></a></span></p>\n<p>Odměnou za vyřešení ti bude kompletní grafická hra Had. Gratuluji!</p>\n<h2>Optimalizace, úklid</h2>\n<p>Než se po dokončení základní hry vrhneš na její rozšiřování, měl by se celý kód\nuklidit a zpřehlednit, aby se v něm další úpravy dělaly snáze a s menším\nrizikem, že se něco pokazí.</p>\n<p>Body k zamyšlení:</p>\n<ul>\n<li>Pokud se ti tam opakuje nějaký kousek kódu vícekrát, možná by se dal\nvložit do funkce nebo cyklu.</li>\n<li>Mají všechny proměnné smysluplná jména?</li>\n<li>Při vykreslování možná tvoříš pro každý kousek hada nový <code>Sprite</code> a ten\nje po vykreslení zapomenut. Optimálnější by možná bylo použít seznam\na v něm všechny instance třídy <code>Sprite</code> uchovávat a používat znovu a znovu.\n<code>Sprite</code> přeci můžeme posunout na libovolné místo i změnit obrázek, který\nobsahuje.</li>\n<li>Používáš globální proměnné? Nebylo by lepší mít jednu třídu pro stav hry\na v ní všechny podstatné informace a metody?</li>\n<li>Funguje ovládání dle tvých představ nebo by šlo nějak zlepšit?</li>\n</ul>\n\n\n " } } }