Většina videoher má celý herní svět uložený jako spoustu čísel, textů, seznamů a jiných datových objektů, které popisují všechno, co ve hře je. Tenhle stav se časem mění, ať už automaticky nebo podle akcí hráče. A docela často – většinou zhruba šedesátkrát za vteřinu – se stav hry převede na obrázek, který se hráčovi ukáže.
Abys mohl/a zobrazit hada, budeš napřed muset definovat stav hry – zadat to, co se má vykreslovat.
Zkus se zamyslet, co všechno bude ten stav obsahovat: co všechno si počítač musí o hře „pamatovat“, aby mohl aktuální stav zobrazit?
Bude potřebovat například aktuální polohu všech částí hada: kde má začátek? Kroutí se doprava nebo doleva? Jak je dlouhý? Naopak barvu hada ve stavu uložit nepotřebuješ – každý had v téhle hře bude stejný.
Napadne tě, jak polohu hada zapsat pomocí čísel, seznamů a dalších základních datových typů?
Asi nejjednodušší způsob, jak si v počítači „zapamatovat“ herního hada, je pomocí seznamu souřadnic.
Pamatuješ si ze školy na kartézské souřadnice? To je taková ta část matematiky, co možná vypadala že nemá praktické využití. Pro počítačovou grafiku jsou ale souřadnice to co pro češtinu písmenka. Pojďme si je osvěžit.
Každý bod v rovině (třeba na obrazovce!) je možné popsat dvěmi čísly: x-ovou a y-ovou souřadnicí. Ta x-ová říká, jak moc vlevo je bod od nějakého počátku, ta y-ová udává jak moc je nahoře. My za onen „počátek“ zvolíme roh okýnka, ve kterém se bude náš had plazit.
Na rozdíl od školní geometrie se had bude plazit po čtverečkové mřížce. Je to jako na šachovnici – když jde pěšec na D5, D značí, jak moc je to políčko vlevo od okraje a 5 jak moc „nahoře“.
Tady je had, který začíná na souřadnicích (1, 2) a hlavu má na (4, 5):
Možná si všimneš, že matematický zápis souřadnic – (1, 2) – odpovídá způsobu, jak se v Pythonu píšou n-tice. To není náhoda! Dvojice čísel je perfektní způsob, jak uložit souřadnice kousku hada.
Had má ale kousků víc, a jinak dlouzí hadi jich budou mít různý počet. Na to je dobré použít seznam. Seznam souřadnic. A protože souřadnice pro nás budou dvojice čísel, seznam souřadnic bude seznam dvojic čísel.
Had z obrázku výše bude v Pythonu vypadat takto:
snake = [(1, 2), (2, 2), (3, 2), (3, 3), (3, 4), (3, 5), (4, 5)]
Tohle je reprezentace hada – to, co je z hlediska hry potřeba o konkrétním hadovi vědět.
Počítačům (a programátorům?) to takhle stačí. My si to ale zkusme zobrazit barevně, ať hadovi rozumí i hráč naší budoucí hry.
U vykreslování hada musíme vyřešit jeden základní problém: převod logických souřadnic na souřadnice obrazovky.
Displeje počítačů fungují podobně jako naše souřadnicová „šachovnice“: jsou to čtvercové mřížky plné políček. Každému políčku – pixelu – lze nastavit barvu. Hlavní rozdíl proti šachovnici je v tom, že pixelů na obrazovce je mnohem, mnohem víc.
Kdyby byl každý „herní“ čtvereček 10×10 pixelů velký, tak hlava hada z ukázky, která má „herní“ souřadnice (4, 5), se na obrazovku bude vykreslovat na čtverečku, který začíná na (40, 50):
A ocas s „herními“ (logickými) souřadnicemi (1, 2) se vykreslí na čtvereček se souřadnicemi (10, 20).
Na to, abychom hada vykreslili, použijeme okýnko z Pygletu. Tady je základní kostra Pygletí aplikace, které už bys měl/a rozumět:
import pyglet
window = pyglet.window.Window()
@window.event
def on_draw():
window.clear()
pyglet.app.run()
V editoru si otevři nový soubor, ulož ho jako had.py
a kostru programu
do něj zkopíruj.
Budeme ji dál rozvíjet.
Stáhni si soubor green.png – zelený čtvereček –
a dej ho do adresáře, kam píšeš kód.
Pod import pyglet
přidej řádek, který tento obrázek načte.
green_image = pyglet.image.load('green.png')
Potom zkus dovnitř do funkce on_draw
přidat vykreslení obrázku na souřadnice
(40, 50), velikosti 10.
green_image.blit(40, 50, width=10, height=10)
Program spusť (cd
do nového adresáře; python had.py
). Funguje?
(Je docela důležité, aby fungoval – nevidíš-li zelený čtvereček,
nečti dál a program radši oprav.)
Jak vidíš, čtvereček je docela malý. Budeme radši používat čtverečky větší, řekněme 64 pixelů.
To číslo je „střelené od boku“.
V programu ho použijeme několikrát, a možná ho později budeš chtít upravit.
Uložíme si ho proto do konstanty (proměnné, kterou nebudeme měnit).
Konstanty se tradičně pojmenovávají velkými písmeny a píšou se hned za řádek
import
(i když to není technicky nutné).
Přidej tedy za import
řádek:
TILE_SIZE = 64
… a ve volání green.blit
velikost čtverečku zohledni:
green_image.blit(4 * TILE_SIZE, 5 * TILE_SIZE,
width=TILE_SIZE, height=TILE_SIZE)
Povedlo se? Máš čtvereček? Jestli ne, zkus si program celý, řádek po řádce, projít a zkontrolovat. Nebo ho porovnej se vzorovým řešením (což je rychlejší varianta, ale míň se naučíš).
Zkus teď na začátek programu – těsně pod import
a konstantu – přidat
definici hada:
snake = [(1, 2), (2, 2), (3, 2), (3, 3), (3, 4), (3, 5), (4, 5)]
A ve funkci draw
vykresli všechny čtverečky hada.
Vzpomeň si, že seznam dvojic můžeš „projít“ pomocí cyklu for
a „rozbalení“
n-tice:
for x, y in snake:
...
Funguje to? Vidíš v tom – aspoň zhruba – hada poskládaného ze čtverečků?
Jestli ne, nezoufej, zkontroluj si to znovu, poptej se na radu. Ukázkové řešení využij až jako krajní možnost, jak pokračovat dál. Nebo pro kontrolu.
Aby bylo ve hře co dělat, budeme potřebovat pro hada krmení.
Stáhni si do adresáře s projektem obrázek
apple.png a zkus vykreslit
jablíčka na následující souřadnice:
food = [(2, 0), (5, 1), (1, 4)]
Možná si všimneš, že obrázek má ve hře trošičku „zubaté“ hrany.
To je dáno způsobem, jakým v Pygletu vykreslujeme.
Úplné vysvětlení by se do tohoto návodu nevešlo, potřebuje trochu hlubší
znalosti počítačové grafiky.
Proto uvedu jen řešení.
Do funkce on_draw
, hned za clear
, dej následující tři řádky:
# Lepší vykreslování (pro nás zatím kouzelné zaříkadlo)
pyglet.gl.glEnable(pyglet.gl.GL_BLEND)
pyglet.gl.glBlendFunc(pyglet.gl.GL_SRC_ALPHA, pyglet.gl.GL_ONE_MINUS_SRC_ALPHA)
Teď, když umíš kreslit hada ze čtverců, zkusíme ho udělat hezčího.
Stáhni si archiv snake-tiles.zip
a rozbal si ho tak, aby adresář snake-tiles
s obrázky byl na stejné úrovni
jako program s hrou.
Struktura adresáře by měla vypadat takhle:
V archivuje spousta „kousků“ hada, které můžeme vykreslovat místo zelených čtverečků. Kousky vypadají následovně. Všimni si pojmenování – každý kousek hada buď spojuje dvě strany obrázku, nebo stranu obrázku s hlavou či ocasem. Obrázek se jmenuje odkud-kam.png.
Co jsou taková ta divná „hadí vajíčka”?
To je pro případ, že by had byl jen jedno políčko dlouhý – a tedy měl hlavu
i ocas na stejném políčku.
V dodělané hře se do takového stavu nedostaneme (had bude začínat s délkou 2),
ale než hru dokončíme, budou tyhle obrázky užitečné.
Pojďme si teď tyhle obrázky načíst. Šlo by to dělat postupně, třeba takhle:
bottom_left = pyglet.image.load('snake-tiles/bottom-left.png')
bottom_right = pyglet.image.load('snake-tiles/bottom-right.png')
bottom_top = pyglet.image.load('snake-tiles/bottom-top.png')
...
Ale obrázků je spousta, tímhle způsobem by to bylo zdlouhavé a nejspíš bys na některý zapomněl/a.
Proto Pythonu řekneme, aby nám dal všechny soubory s koncovkou .png
v daném
adresáři.
Na to se dá použít třída Path
z modulu pathlib
.
Zkus si do nového souboru, třeba experiment.py
, napsat následující kód
a spustit ho.
Dokážeš vysvětlit, co dělá?
from pathlib import Path
TILES_DIRECTORY = Path('snake-tiles')
for path in TILES_DIRECTORY.glob('*.png'):
print(path)
My z každého souboru potřebujeme nejlépe jméno, tedy místo
snake-tiles/right-end.png
jenom right-end
.
Na to naštěstí existuje atribut stem
(kořen, t.j. jméno bez přípony).
Místo print(path)
použij:
print(path.stem)
Funguje? Máš vypsané všechny možné kousky hada?
Teď budeme chtít načíst obrázky do slovníku. Klíče slovníku, podle kterých budeme vyhledávat, budou jména, která jsi právě vypsal/a. Hodnoty pak budou pygletí obrázky, které ve hře můžeš rovnou vykreslit.
Začni s prázdným slovníkem, {}
, a v cyklu for
do něj postupně přidávej
záznamy.
Pak celý slovník vypiš.
Až to budeš mít, měl by výpis vypadat asi takhle:
{'right-tongue': <ImageData 64x64>, 'top-tongue': <ImageData 64x64>,
'right-top': <ImageData 64x64>, 'left-bottom': <ImageData 64x64>,
'end-left': <ImageData 64x64>, 'bottom-tongue': <ImageData 64x64>,
'left-top': <ImageData 64x64>, 'bottom-bottom': <ImageData 64x64>,
...
A teď zkus načtení obrázků začlenit do programu s hadem!
Všechny importy patří nahoru, konstanty pod ně, a dál pak zbytek kódu.
Vypisovat načtený slovník ve hře nemusíš.
Zato ve vykreslovací funkci použij místo green_image
třeba snake_tiles['end-end']
.
Místo čtverečků se teď objeví kuličky – místo hada budeš mít „housenku“.
Místo toho, aby byl všude stejný kousek hada, ale budeme chtít vybrat vždycky ten správný.
Jak na to? Podle čeho ho vybrat?
Pojďme si to vyzkoušet vedle.
Vytvoř soubor smery.py
a napiš do něj:
snake = [(1, 2), (2, 2), (3, 2), (3, 3), (3, 4), (3, 5), (4, 5)]
for x, y in snake:
print(x, y)
Tenhle kód vypisuje souřadnice:
1 2
2 2
3 2
3 3
3 4
3 5
4 5
Zkus vymyslet, jak by se tenhle kód dal změnit, aby vypisoval ke každé souřadnici směr k předchozímu a následujícímu políčku – tedy odkud a kam každý kousek hada „vede“. Takhle:
1 2 end right
2 2 left right
3 2 left top
3 3 bottom top
3 4 bottom top
3 5 bottom right
4 5 left end
Toto je těžký úkol. Nepředpokládám, že ho zvládneš vyřešit hned, i když všechny potřebné informace a nástroje k tomu znáš. Zkus nad tím ale přemýšlet, nech si to rozležet v hlavě třeba přes noc, vrať se k materiálům k předchozím lekcím (hlavně k úvodu do Pythonu), zkoušej a objevuj… A časem na to přijdeš.
Až se to stane, zkus své řešení co nejvíc zjednodušit a pak ho zakomponovat
do vykreslovací funkce místo existujícího cyklu for x, y in snake
.
for ... in ...:
...
x = ...
y = ...
odkud = ...
kam = ...
...
snake_tiles[odkud + '-' + kam].blit(
x * TILE_SIZE, y * TILE_SIZE, width=TILE_SIZE, height=TILE_SIZE)
Soubor smery.py
po vyřešení nemaž, bude se ti pak hodit.
Odměnou za vyřešení tohoto úkolu ti bude had místo housenky.
Než na to přijdeš, zbytek programu ti neuteče. Housenka je úplně stejně hratelná jako had, jen jinak vypadá. Klidně přejdi na další část – logiku hry – s housenkou.
{ "data": { "sessionMaterial": { "id": "session-material:2018/snake-brno-codeweek:workshop:1", "title": "Kreslení hada", "html": "\n \n \n\n <h1>Nakresli mi hada</h1>\n<p>Většina videoher má celý herní svět uložený jako spoustu čísel, textů, seznamů\na jiných datových objektů, které popisují všechno, co ve hře je.\nTenhle stav se časem mění, ať už automaticky nebo podle akcí hráče.\nA docela často – většinou zhruba šedesátkrát za vteřinu – se stav hry převede\nna obrázek, který se hráčovi ukáže.</p>\n<p>Abys mohl/a zobrazit hada, budeš napřed muset definovat stav hry – zadat\nto, co se má vykreslovat.</p>\n<p>Zkus se zamyslet, co všechno bude ten stav obsahovat: co všechno si počítač\nmusí o hře „pamatovat“, aby mohl aktuální stav zobrazit?</p>\n<p>Bude potřebovat například aktuální polohu všech částí hada: kde má začátek?\nKroutí se doprava nebo doleva? Jak je dlouhý?\nNaopak barvu hada ve stavu uložit nepotřebuješ – každý had v téhle hře bude\nstejný.</p>\n<p>Napadne tě, jak polohu hada zapsat pomocí čísel, seznamů a dalších základních\ndatových typů?</p>\n<h2>Reprezentace hada</h2>\n<p>Asi nejjednodušší způsob, jak si v počítači „zapamatovat“ herního hada,\nje pomocí seznamu souřadnic.</p>\n<p>Pamatuješ si ze školy na kartézské souřadnice?\nTo je taková ta část matematiky, co možná vypadala že nemá praktické využití.\nPro počítačovou grafiku jsou ale souřadnice to co pro češtinu písmenka.\nPojďme si je osvěžit.</p>\n<p>Každý bod v rovině (třeba na obrazovce!)\nje možné popsat dvěmi čísly: <var>x</var>-ovou a <var>y</var>-ovou souřadnicí.\nTa <var>x</var>-ová říká, jak moc vlevo je bod od nějakého počátku,\nta <var>y</var>-ová udává jak moc je nahoře.\nMy za onen „počátek“ zvolíme roh okýnka, ve kterém se bude náš had plazit.</p>\n<p>Na rozdíl od školní geometrie se had bude plazit po čtverečkové mřížce.\nJe to jako na šachovnici – když jde pěšec na D5, D značí, jak moc je to\npolíčko vlevo od okraje a 5 jak moc „nahoře“.</p>\n<p>Tady je had, který začíná na souřadnicích (1, 2) a hlavu má na (4, 5):</p>\n<p><span class=\"figure\"><a href=\"/2018/snake-brno-codeweek/snake/drawing/static/coords.svg\"><img src=\"/2018/snake-brno-codeweek/snake/drawing/static/coords.svg\" alt=\"Had na „šachovnici“ se souřadnicemi\"></a></span></p>\n<p>Možná si všimneš, že matematický zápis souřadnic – (1, 2) – odpovídá\nzpůsobu, jak se v Pythonu píšou <var>n</var>-tice.\nTo není náhoda!\nDvojice čísel je perfektní způsob, jak uložit souřadnice kousku hada.</p>\n<p>Had má ale kousků víc, a jinak dlouzí hadi jich budou mít různý počet.\nNa to je dobré použít seznam. Seznam souřadnic.\nA protože souřadnice pro nás budou dvojice čísel,\nseznam souřadnic bude seznam dvojic čísel.</p>\n<p>Had z obrázku výše bude v Pythonu vypadat takto:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">snake</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">3</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">)]</span>\n</pre></div><p>Tohle je reprezentace hada – to, co je z hlediska hry potřeba o konkrétním\nhadovi vědět.</p>\n<p>Počítačům (a programátorům?) to takhle stačí.\nMy si to ale zkusme zobrazit barevně, ať hadovi rozumí i hráč naší budoucí hry.</p>\n<h2>Logické a zobrazovací souřadnice</h2>\n<p>U vykreslování hada musíme vyřešit jeden základní problém:\npřevod <em>logických souřadnic</em> na souřadnice <em>obrazovky</em>.</p>\n<p>Displeje počítačů fungují podobně jako naše souřadnicová „šachovnice“:\njsou to čtvercové mřížky plné políček.\nKaždému políčku – <em>pixelu</em> – lze nastavit barvu.\nHlavní rozdíl proti šachovnici je v tom, že pixelů na obrazovce je mnohem,\nmnohem víc.</p>\n<p>Kdyby byl každý „herní“ čtvereček 10×10 pixelů velký,\ntak hlava hada z ukázky, která má „herní“ souřadnice (4, 5),\nse na obrazovku bude vykreslovat na čtverečku, který začíná na (40, 50):</p>\n<p><span class=\"figure\"><a href=\"/2018/snake-brno-codeweek/snake/drawing/static/coords-px.svg\"><img src=\"/2018/snake-brno-codeweek/snake/drawing/static/coords-px.svg\" alt=\"Had na „šachovnici“ se souřadnicemi obrazovky\"></a></span></p>\n<p>A ocas s „herními“ (<em>logickými</em>) souřadnicemi (1, 2) se vykreslí na čtvereček\nse souřadnicemi (10, 20).</p>\n<h2>Sázení čtverečku</h2>\n<p>Na to, abychom hada vykreslili, použijeme okýnko z Pygletu.\nTady je základní kostra Pygletí aplikace, které už bys měl/a rozumět:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">pyglet</span>\n\n<span class=\"n\">window</span> <span class=\"o\">=</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">Window</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@window.event</span>\n<span class=\"k\">def</span> <span class=\"nf\">on_draw</span><span class=\"p\">():</span>\n <span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">clear</span><span class=\"p\">()</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">app</span><span class=\"o\">.</span><span class=\"n\">run</span><span class=\"p\">()</span>\n</pre></div><p>V editoru si otevři nový soubor, ulož ho jako <code>had.py</code> a kostru programu\ndo něj zkopíruj.\nBudeme ji dál rozvíjet.</p>\n<p><img src=\"/2018/snake-brno-codeweek/snake/drawing/static/green.png\" alt style=\"display:block; float:right; margin: 2px; border: 1px solid #ccc; border-radius: 1px;\">\nStáhni si soubor <a href=\"/2018/snake-brno-codeweek/snake/drawing/static/green.png\">green.png</a> – zelený čtvereček –\na dej ho do adresáře, kam píšeš kód.</p>\n<p>Pod <code>import pyglet</code> přidej řádek, který tento obrázek načte.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">green_image</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=\"s1\">'green.png'</span><span class=\"p\">)</span>\n</pre></div><p>Potom zkus dovnitř do funkce <code>on_draw</code> přidat vykreslení obrázku na souřadnice\n(40, 50), velikosti 10.</p>\n<div class=\"highlight\"><pre><span></span> <span class=\"n\">green_image</span><span class=\"o\">.</span><span class=\"n\">blit</span><span class=\"p\">(</span><span class=\"mi\">40</span><span class=\"p\">,</span> <span class=\"mi\">50</span><span class=\"p\">,</span> <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"mi\">10</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"mi\">10</span><span class=\"p\">)</span>\n</pre></div><p>Program spusť (<code>cd</code> do nového adresáře; <code>python had.py</code>). Funguje?\n(Je docela důležité, aby fungoval – nevidíš-li zelený čtvereček,\nnečti dál a program radši oprav.)</p>\n<p>Jak vidíš, čtvereček je docela malý.\nBudeme radši používat čtverečky větší, řekněme 64 pixelů.</p>\n<p>To číslo je „střelené od boku“.\nV programu ho použijeme několikrát, a možná ho později budeš chtít upravit.\nUložíme si ho proto do <em>konstanty</em> (proměnné, kterou nebudeme měnit).\nKonstanty se tradičně pojmenovávají velkými písmeny a píšou se hned za řádek\n<code>import</code> (i když to není technicky nutné).\nPřidej tedy za <code>import</code> řádek:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">TILE_SIZE</span> <span class=\"o\">=</span> <span class=\"mi\">64</span>\n</pre></div><p>… a ve volání <code>green.blit</code> velikost čtverečku zohledni:</p>\n<div class=\"highlight\"><pre><span></span> <span class=\"n\">green_image</span><span class=\"o\">.</span><span class=\"n\">blit</span><span class=\"p\">(</span><span class=\"mi\">4</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"mi\">5</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span>\n <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">)</span>\n</pre></div><p>Povedlo se? Máš čtvereček?\nJestli ne, zkus si program celý, řádek po řádce, projít a zkontrolovat.\nNebo ho porovnej se vzorovým řešením (což je rychlejší varianta, ale míň\nse naučíš).</p>\n<div class=\"solution\" id=\"solution-0\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2018/snake-brno-codeweek/snake/drawing/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\">import</span> <span class=\"nn\">pyglet</span>\n\n<span class=\"n\">TILE_SIZE</span> <span class=\"o\">=</span> <span class=\"mi\">64</span>\n<span class=\"n\">green_image</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=\"s1\">'green.png'</span><span class=\"p\">)</span>\n\n<span class=\"n\">window</span> <span class=\"o\">=</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">Window</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@window.event</span>\n<span class=\"k\">def</span> <span class=\"nf\">on_draw</span><span class=\"p\">():</span>\n <span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">clear</span><span class=\"p\">()</span>\n <span class=\"n\">green_image</span><span class=\"o\">.</span><span class=\"n\">blit</span><span class=\"p\">(</span><span class=\"mi\">4</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"mi\">5</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span>\n <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">)</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">app</span><span class=\"o\">.</span><span class=\"n\">run</span><span class=\"p\">()</span>\n</pre></div>\n </div>\n</div><h2>Sázení hada</h2>\n<p>Zkus teď na začátek programu – těsně pod <code>import</code> a konstantu – přidat\ndefinici hada:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">snake</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">3</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">)]</span>\n</pre></div><p>A ve funkci <code>draw</code> vykresli všechny čtverečky hada.\nVzpomeň si, že seznam dvojic můžeš „projít“ pomocí cyklu <code>for</code> a „rozbalení“\n<var>n</var>-tice:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">for</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">snake</span><span class=\"p\">:</span>\n <span class=\"o\">...</span>\n</pre></div><p>Funguje to? Vidíš v tom – aspoň zhruba – hada poskládaného ze čtverečků?</p>\n<p><span class=\"figure\"><a href=\"/2018/snake-brno-codeweek/snake/drawing/static/coords-blocks.svg\"><img src=\"/2018/snake-brno-codeweek/snake/drawing/static/coords-blocks.svg\" alt=\"Had na „šachovnici“ a ukázka programu\"></a></span></p>\n<p>Jestli ne, nezoufej, zkontroluj si to znovu, poptej se na radu.\nUkázkové řešení využij až jako krajní možnost, jak pokračovat dál.\nNebo pro kontrolu.</p>\n<div class=\"solution\" id=\"solution-1\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2018/snake-brno-codeweek/snake/drawing/index/solutions/1/\"><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\">import</span> <span class=\"nn\">pyglet</span>\n\n<span class=\"n\">TILE_SIZE</span> <span class=\"o\">=</span> <span class=\"mi\">64</span>\n\n<span class=\"n\">snake</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">3</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">)]</span>\n\n<span class=\"n\">green_image</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=\"s1\">'green.png'</span><span class=\"p\">)</span>\n\n<span class=\"n\">window</span> <span class=\"o\">=</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">Window</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@window.event</span>\n<span class=\"k\">def</span> <span class=\"nf\">on_draw</span><span class=\"p\">():</span>\n <span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">clear</span><span class=\"p\">()</span>\n <span class=\"k\">for</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">snake</span><span class=\"p\">:</span>\n <span class=\"n\">green_image</span><span class=\"o\">.</span><span class=\"n\">blit</span><span class=\"p\">(</span><span class=\"n\">x</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span>\n <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">)</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">app</span><span class=\"o\">.</span><span class=\"n\">run</span><span class=\"p\">()</span>\n</pre></div>\n </div>\n</div><h2>Krmení</h2>\n<p><img src=\"/2018/snake-brno-codeweek/snake/drawing/static/apple.png\" alt style=\"display:block; float:right; margin: 2px; border: 1px solid #ccc; border-radius: 1px;\">\nAby bylo ve hře co dělat, budeme potřebovat pro hada krmení.\nStáhni si do adresáře s projektem obrázek\n<a href=\"/2018/snake-brno-codeweek/snake/drawing/static/apple.png\">apple.png</a> a zkus vykreslit\njablíčka na následující souřadnice:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">food</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">0</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">5</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">)]</span>\n</pre></div><div class=\"solution\" id=\"solution-2\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2018/snake-brno-codeweek/snake/drawing/index/solutions/2/\"><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\">import</span> <span class=\"nn\">pyglet</span>\n\n<span class=\"n\">TILE_SIZE</span> <span class=\"o\">=</span> <span class=\"mi\">64</span>\n\n<span class=\"n\">snake</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">3</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">)]</span>\n<span class=\"n\">food</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">0</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">5</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">)]</span>\n\n<span class=\"n\">red_image</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=\"s1\">'apple.png'</span><span class=\"p\">)</span>\n<span class=\"n\">green_image</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=\"s1\">'green.png'</span><span class=\"p\">)</span>\n\n<span class=\"n\">window</span> <span class=\"o\">=</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">Window</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@window.event</span>\n<span class=\"k\">def</span> <span class=\"nf\">on_draw</span><span class=\"p\">():</span>\n <span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">clear</span><span class=\"p\">()</span>\n <span class=\"k\">for</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">snake</span><span class=\"p\">:</span>\n <span class=\"n\">green_image</span><span class=\"o\">.</span><span class=\"n\">blit</span><span class=\"p\">(</span><span class=\"n\">x</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span>\n <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">)</span>\n <span class=\"k\">for</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">food</span><span class=\"p\">:</span>\n <span class=\"n\">red_image</span><span class=\"o\">.</span><span class=\"n\">blit</span><span class=\"p\">(</span><span class=\"n\">x</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span>\n <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">)</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">app</span><span class=\"o\">.</span><span class=\"n\">run</span><span class=\"p\">()</span>\n</pre></div>\n </div>\n</div><p>Možná si všimneš, že obrázek má ve hře trošičku „zubaté“ hrany.\nTo je dáno způsobem, jakým v Pygletu vykreslujeme.\nÚplné vysvětlení by se do tohoto návodu nevešlo, potřebuje trochu hlubší\nznalosti počítačové grafiky.\nProto uvedu jen řešení.\nDo funkce <code>on_draw</code>, hned za <code>clear</code>, dej následující tři řádky:</p>\n<div class=\"highlight\"><pre><span></span> <span class=\"c1\"># Lepší vykreslování (pro nás zatím kouzelné zaříkadlo)</span>\n <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">glEnable</span><span class=\"p\">(</span><span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">GL_BLEND</span><span class=\"p\">)</span>\n <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">glBlendFunc</span><span class=\"p\">(</span><span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">GL_SRC_ALPHA</span><span class=\"p\">,</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">GL_ONE_MINUS_SRC_ALPHA</span><span class=\"p\">)</span>\n</pre></div><h2>Načítání kousků hada</h2>\n<p>Teď, když umíš kreslit hada ze čtverců, zkusíme ho udělat hezčího.\nStáhni si archiv <a href=\"/2018/snake-brno-codeweek/snake/drawing/static/snake-tiles.zip\">snake-tiles.zip</a>\na rozbal si ho tak, aby adresář <code>snake-tiles</code> s obrázky byl na stejné úrovni\njako program s hrou.\nStruktura adresáře by měla vypadat takhle:</p>\n<p><span class=\"figure\"><a href=\"/2018/snake-brno-codeweek/snake/drawing/static/screenshot-dir.png\"><img src=\"/2018/snake-brno-codeweek/snake/drawing/static/screenshot-dir.png\" alt=\"Adresářová struktura\"></a></span></p>\n<p>V archivuje spousta „kousků“ hada, které můžeme vykreslovat místo zelených\nčtverečků.\nKousky vypadají následovně.\nVšimni si pojmenování – každý kousek hada buď spojuje dvě strany obrázku,\nnebo stranu obrázku s hlavou či ocasem.\nObrázek se jmenuje <var>odkud</var>-<var>kam</var>.png.</p>\n<p><span class=\"figure\"><a href=\"/2018/snake-brno-codeweek/snake/drawing/static/snake-tiles.png\"><img src=\"/2018/snake-brno-codeweek/snake/drawing/static/snake-tiles.png\" alt=\"Kousky hada\"></a></span></p>\n<div class=\"admonition note\"><p>Co jsou taková ta divná „hadí vajíčka”?\n<img src=\"/2018/snake-brno-codeweek/snake/drawing/static/snake-tiles/end-end.png\" alt style=\"display:block; float:left; margin: 2px; border: 1px solid #ccc; border-radius: 1px;\">\nTo je pro případ, že by had byl jen jedno políčko dlouhý – a tedy měl hlavu\ni ocas na stejném políčku.\nV dodělané hře se do takového stavu nedostaneme (had bude začínat s délkou 2),\nale než hru dokončíme, budou tyhle obrázky užitečné.</p>\n</div><p>Pojďme si teď tyhle obrázky <em>načíst</em>.\nŠlo by to dělat postupně, třeba takhle:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">bottom_left</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=\"s1\">'snake-tiles/bottom-left.png'</span><span class=\"p\">)</span>\n<span class=\"n\">bottom_right</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=\"s1\">'snake-tiles/bottom-right.png'</span><span class=\"p\">)</span>\n<span class=\"n\">bottom_top</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=\"s1\">'snake-tiles/bottom-top.png'</span><span class=\"p\">)</span>\n<span class=\"o\">...</span>\n</pre></div><p>Ale obrázků je spousta, tímhle způsobem by to bylo zdlouhavé a nejspíš bys\nna některý zapomněl/a.</p>\n<p>Proto Pythonu řekneme, aby nám dal všechny soubory s koncovkou <code>.png</code> v daném\nadresáři.\nNa to se dá použít třída <code>Path</code> z modulu <a href=\"https://docs.python.org/3/library/pathlib.html\"><code>pathlib</code></a>.\nZkus si do nového souboru, třeba <code>experiment.py</code>, napsat následující kód\na spustit ho.\nDokážeš vysvětlit, co dělá?</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\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=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">path</span><span class=\"p\">)</span>\n</pre></div><p>My z každého souboru potřebujeme nejlépe jméno, tedy místo\n<code>snake-tiles/right-end.png</code> jenom <code>right-end</code>.\nNa to naštěstí existuje atribut <code>stem</code> (<em>kořen</em>, t.j. jméno bez přípony).\nMísto <code>print(path)</code> použij:</p>\n<div class=\"highlight\"><pre><span></span> <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">stem</span><span class=\"p\">)</span>\n</pre></div><p>Funguje? Máš vypsané všechny možné kousky hada?</p>\n<p>Teď budeme chtít načíst obrázky do <em>slovníku</em>.\n<em>Klíče</em> slovníku, podle kterých budeme vyhledávat, budou jména, která jsi\nprávě vypsal/a.\n<em>Hodnoty</em> pak budou pygletí obrázky, které ve hře můžeš rovnou vykreslit.</p>\n<p>Začni s prázdným slovníkem, <code>{}</code>, a v cyklu <code>for</code> do něj postupně přidávej\nzáznamy.\nPak celý slovník vypiš.</p>\n<p>Až to budeš mít, měl by výpis vypadat asi takhle:</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 'end-left': <ImageData 64x64>, 'bottom-tongue': <ImageData 64x64>,\n 'left-top': <ImageData 64x64>, 'bottom-bottom': <ImageData 64x64>,\n ...</code></pre></div><div class=\"solution\" id=\"solution-3\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2018/snake-brno-codeweek/snake/drawing/index/solutions/3/\"><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><h2>Housenka</h2>\n<p>A teď zkus načtení obrázků začlenit do programu s hadem!</p>\n<p>Všechny importy patří nahoru, konstanty pod ně, a dál pak zbytek kódu.\nVypisovat načtený slovník ve hře nemusíš.\nZato ve vykreslovací funkci použij místo <code>green_image</code>\ntřeba <code>snake_tiles['end-end']</code>.</p>\n<p>Místo čtverečků se teď objeví kuličky – místo hada budeš mít „housenku“.</p>\n<p><span class=\"figure\"><a href=\"/2018/snake-brno-codeweek/snake/drawing/static/caterpillar.png\"><img src=\"/2018/snake-brno-codeweek/snake/drawing/static/caterpillar.png\" alt=\"Housenka\"></a></span></p>\n<div class=\"solution\" id=\"solution-4\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2018/snake-brno-codeweek/snake/drawing/index/solutions/4/\"><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\">TILE_SIZE</span> <span class=\"o\">=</span> <span class=\"mi\">64</span>\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</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">3</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">)]</span>\n<span class=\"n\">food</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">0</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">5</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">)]</span>\n\n<span class=\"n\">red_image</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=\"s1\">'apple.png'</span><span class=\"p\">)</span>\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=\"n\">window</span> <span class=\"o\">=</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">Window</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@window.event</span>\n<span class=\"k\">def</span> <span class=\"nf\">on_draw</span><span class=\"p\">():</span>\n <span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">clear</span><span class=\"p\">()</span>\n <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">glEnable</span><span class=\"p\">(</span><span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">GL_BLEND</span><span class=\"p\">)</span>\n <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">glBlendFunc</span><span class=\"p\">(</span><span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">GL_SRC_ALPHA</span><span class=\"p\">,</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">gl</span><span class=\"o\">.</span><span class=\"n\">GL_ONE_MINUS_SRC_ALPHA</span><span class=\"p\">)</span>\n <span class=\"k\">for</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">snake</span><span class=\"p\">:</span>\n <span class=\"n\">snake_tiles</span><span class=\"p\">[</span><span class=\"s1\">'end-end'</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">blit</span><span class=\"p\">(</span>\n <span class=\"n\">x</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">)</span>\n <span class=\"k\">for</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">food</span><span class=\"p\">:</span>\n <span class=\"n\">red_image</span><span class=\"o\">.</span><span class=\"n\">blit</span><span class=\"p\">(</span>\n <span class=\"n\">x</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">)</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">app</span><span class=\"o\">.</span><span class=\"n\">run</span><span class=\"p\">()</span>\n</pre></div>\n </div>\n</div><h2>Jak vybrat čtverečky?</h2>\n<p>Místo toho, aby byl všude stejný kousek hada,\nale budeme chtít vybrat vždycky ten správný.</p>\n<p>Jak na to?\nPodle čeho ho vybrat?</p>\n<p>Pojďme si to vyzkoušet vedle.\nVytvoř soubor <code>smery.py</code> a napiš do něj:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">snake</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">3</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">)]</span>\n\n<span class=\"k\">for</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">snake</span><span class=\"p\">:</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">)</span>\n</pre></div><p>Tenhle kód vypisuje souřadnice:</p>\n<div class=\"highlight\"><pre><code>1 2\n2 2\n3 2\n3 3\n3 4\n3 5\n4 5</code></pre></div><p>Zkus vymyslet, jak by se tenhle kód dal změnit, aby vypisoval ke každé\nsouřadnici <em>směr</em> k předchozímu a následujícímu políčku – tedy odkud a kam\nkaždý kousek hada „vede“.\nTakhle:</p>\n<div class=\"highlight\"><pre><code>1 2 end right\n2 2 left right\n3 2 left top\n3 3 bottom top\n3 4 bottom top\n3 5 bottom right\n4 5 left end</code></pre></div><p>Toto je <strong>těžký úkol</strong>.\nNepředpokládám, že ho zvládneš vyřešit hned, i když všechny potřebné informace\na nástroje k tomu znáš.\nZkus nad tím ale přemýšlet, nech si to rozležet v hlavě třeba přes noc,\nvrať se k materiálům k předchozím lekcím (hlavně k úvodu do Pythonu),\nzkoušej a objevuj… A časem na to přijdeš.</p>\n<p>Až se to stane, zkus své řešení co nejvíc <em>zjednodušit</em> a pak ho zakomponovat\ndo vykreslovací funkce místo existujícího cyklu <code>for x, y in snake</code>.</p>\n<div class=\"highlight\"><pre><span></span> <span class=\"k\">for</span> <span class=\"o\">...</span> <span class=\"ow\">in</span> <span class=\"o\">...</span><span class=\"p\">:</span>\n <span class=\"o\">...</span>\n <span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"o\">...</span>\n <span class=\"n\">y</span> <span class=\"o\">=</span> <span class=\"o\">...</span>\n <span class=\"n\">odkud</span> <span class=\"o\">=</span> <span class=\"o\">...</span>\n <span class=\"n\">kam</span> <span class=\"o\">=</span> <span class=\"o\">...</span>\n <span class=\"o\">...</span>\n\n <span class=\"n\">snake_tiles</span><span class=\"p\">[</span><span class=\"n\">odkud</span> <span class=\"o\">+</span> <span class=\"s1\">'-'</span> <span class=\"o\">+</span> <span class=\"n\">kam</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">blit</span><span class=\"p\">(</span>\n <span class=\"n\">x</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"o\">*</span> <span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"n\">TILE_SIZE</span><span class=\"p\">)</span>\n</pre></div><p>Soubor <code>smery.py</code> po vyřešení nemaž, bude se ti pak hodit.</p>\n<p>Odměnou za vyřešení tohoto úkolu ti bude had místo housenky.</p>\n<p>Než na to přijdeš, zbytek programu ti neuteče.\nHousenka je úplně stejně hratelná jako had, jen jinak vypadá.\nKlidně přejdi na další část – logiku hry – s housenkou.</p>\n\n\n " } } }