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 mohla 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.
Angličtina
Teď, když děláme profesionální software, zkusíme začít používat pro
jména proměnných, funkcí a podobně univerzálnější jazyk než je čeština.
Moje proměnná se jmenuje snake
místo had
.
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ěla 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:
...
Zvládneš to? Ve výsledku by měl být vidět – aspoň zhruba – had poskládaný ze čtverečků.
Jestli to nefunguje, 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. Anebo 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ěla.
Proto si obrázky načteme automaticky, v cyklu, a dáme je do slovníku.
Program bude vypadat takhle:
bottom
, end
, left
, right
, top
):bottom
, end
, left
, right
, top
, dead
, tongue
):snake_tiles = {}
for start in ['bottom', 'end', 'left', 'right', 'top']:
for end in ['bottom', 'end', 'left', 'right', 'top', 'dead', 'tongue']:
key = start + '-' + end
image = pyglet.image.load('snake-tiles/' + key + '.png')
snake_tiles[key] = image
Pak celý slovník vypiš. Výpis bude vypadat dost nepřehledně, ale třeba v něm poznáš slovník – {klíč: hodnota, klíč: hodnota, ...}:
{'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, budeme chtít vybrat vždycky ten správný.
Jak na to? Podle čeho ho vybrat?
Obrázky s kousky hada jsou pojmenovány
odkud-kam.png
.
To není náhoda – ukazuje to, co potřebuješ vědět, abys mohla ten správný
kousek vybrat.
Když máš hada podle následujícího obrázku, na políčko (3, 2) patří
kousek, na kterém had „leze“ zleva nahoru – tedy left-top.png
Pro každé z políček budeš potřebovat zjistit, odkud a kam na něm had leze – tedy směr k předchozí a následující souřadnici.
Potřebuješ pro každé políčko hada zjistit
Do programu se pak dají hodnoty zadat nějak takto:
for ... in ...: # čím bude cyklus procházet? Samotným self.snake?
x = ...
y = ...
before = ... # Směr k předchozímu políčku ('left' nebo 'top' nebo ...)
after = ... # Směr k následujícímu políčku
snake_tiles[before + '-' + after].blit(
x * TILE_SIZE, y * TILE_SIZE, width=TILE_SIZE, height=TILE_SIZE)
Toto je těžký úkol. I když všechny potřebné informace a nástroje k tomu teď teoreticky znáš, je potřeba je správným způsobem poskládat dohromady. Tohle skládání dohromady, návrh algoritmů, je nejsložitější programátorská disciplína.
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š. Odměnou za vyřešení 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 psaní logiky hry s housenkou.
Nebo se necháš poddat?
{ "data": { "sessionMaterial": { "id": "session-material:2019/brno-podzim-snake:workshop:2", "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 mohla 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=\"/2019/brno-podzim-snake/snake/drawing/static/coords.svg\"><img src=\"/2019/brno-podzim-snake/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<div class=\"admonition note\"><p class=\"admonition-title\">Angličtina</p>\n<p>Teď, když děláme profesionální software, zkusíme začít používat pro\njména proměnných, funkcí a podobně univerzálnější jazyk než je čeština.\nMoje proměnná se jmenuje <code>snake</code> místo <code>had</code>.</p>\n</div><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=\"/2019/brno-podzim-snake/snake/drawing/static/coords-px.svg\"><img src=\"/2019/brno-podzim-snake/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ěla 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=\"/2019/brno-podzim-snake/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=\"/2019/brno-podzim-snake/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=\"/2019/brno-podzim-snake/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>Zvládneš to?\nVe výsledku by měl být vidět – aspoň zhruba – had poskládaný ze čtverečků.</p>\n<p><span class=\"figure\"><a href=\"/2019/brno-podzim-snake/snake/drawing/static/coords-blocks.svg\"><img src=\"/2019/brno-podzim-snake/snake/drawing/static/coords-blocks.svg\" alt=\"Had na „šachovnici“ a ukázka programu\"></a></span></p>\n<p>Jestli to nefunguje, 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.\nAnebo pro kontrolu!</p>\n<div class=\"solution\" id=\"solution-1\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/brno-podzim-snake/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=\"/2019/brno-podzim-snake/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=\"/2019/brno-podzim-snake/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=\"/2019/brno-podzim-snake/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=\"/2019/brno-podzim-snake/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=\"/2019/brno-podzim-snake/snake/drawing/static/screenshot-dir.png\"><img src=\"/2019/brno-podzim-snake/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=\"/2019/brno-podzim-snake/snake/drawing/static/snake-tiles.png\"><img src=\"/2019/brno-podzim-snake/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=\"/2019/brno-podzim-snake/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ěla.</p>\n<p>Proto si obrázky načteme automaticky, v cyklu, a dáme je do slovníku.</p>\n<p>Program bude vypadat takhle:</p>\n<ul>\n<li>Začni s prázdným slovníkem.</li>\n<li>Pro každý <em>začátek</em> (<code>bottom</code>, <code>end</code>, <code>left</code>, <code>right</code>, <code>top</code>):<ul>\n<li>Pro každý <em>konec</em> (<code>bottom</code>, <code>end</code>, <code>left</code>, <code>right</code>, <code>top</code>, <code>dead</code>, <code>tongue</code>):<ul>\n<li>Budeme načítat obrázek „<var>začátek</var>-<var>konec</var>“; tento\n<var>klíč</var> si dej do proměnné</li>\n<li>Načti obrázek <var>klíč</var>.png</li>\n<li>Ulož obrázek do slovníku pod <var>klíč</var>.</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">snake_tiles</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n<span class=\"k\">for</span> <span class=\"n\">start</span> <span class=\"ow\">in</span> <span class=\"p\">[</span><span class=\"s1\">'bottom'</span><span class=\"p\">,</span> <span class=\"s1\">'end'</span><span class=\"p\">,</span> <span class=\"s1\">'left'</span><span class=\"p\">,</span> <span class=\"s1\">'right'</span><span class=\"p\">,</span> <span class=\"s1\">'top'</span><span class=\"p\">]:</span>\n <span class=\"k\">for</span> <span class=\"n\">end</span> <span class=\"ow\">in</span> <span class=\"p\">[</span><span class=\"s1\">'bottom'</span><span class=\"p\">,</span> <span class=\"s1\">'end'</span><span class=\"p\">,</span> <span class=\"s1\">'left'</span><span class=\"p\">,</span> <span class=\"s1\">'right'</span><span class=\"p\">,</span> <span class=\"s1\">'top'</span><span class=\"p\">,</span> <span class=\"s1\">'dead'</span><span class=\"p\">,</span> <span class=\"s1\">'tongue'</span><span class=\"p\">]:</span>\n <span class=\"n\">key</span> <span class=\"o\">=</span> <span class=\"n\">start</span> <span class=\"o\">+</span> <span class=\"s1\">'-'</span> <span class=\"o\">+</span> <span class=\"n\">end</span>\n <span class=\"n\">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\">'snake-tiles/'</span> <span class=\"o\">+</span> <span class=\"n\">key</span> <span class=\"o\">+</span> <span class=\"s1\">'.png'</span><span class=\"p\">)</span>\n <span class=\"n\">snake_tiles</span><span class=\"p\">[</span><span class=\"n\">key</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">image</span>\n</pre></div><p>Pak celý slovník vypiš.\nVýpis bude vypadat dost nepřehledně, ale třeba v něm poznáš slovník –\n<em>{klíč: hodnota, klíč: hodnota, ...}</em>:</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><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=\"/2019/brno-podzim-snake/snake/drawing/static/caterpillar.png\"><img src=\"/2019/brno-podzim-snake/snake/drawing/static/caterpillar.png\" alt=\"Housenka\"></a></span></p>\n<div class=\"solution\" id=\"solution-3\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/brno-podzim-snake/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\">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\">start</span> <span class=\"ow\">in</span> <span class=\"p\">[</span><span class=\"s1\">'bottom'</span><span class=\"p\">,</span> <span class=\"s1\">'end'</span><span class=\"p\">,</span> <span class=\"s1\">'left'</span><span class=\"p\">,</span> <span class=\"s1\">'right'</span><span class=\"p\">,</span> <span class=\"s1\">'top'</span><span class=\"p\">]:</span>\n <span class=\"k\">for</span> <span class=\"n\">end</span> <span class=\"ow\">in</span> <span class=\"p\">[</span><span class=\"s1\">'bottom'</span><span class=\"p\">,</span> <span class=\"s1\">'end'</span><span class=\"p\">,</span> <span class=\"s1\">'left'</span><span class=\"p\">,</span> <span class=\"s1\">'right'</span><span class=\"p\">,</span> <span class=\"s1\">'top'</span><span class=\"p\">,</span> <span class=\"s1\">'dead'</span><span class=\"p\">,</span> <span class=\"s1\">'tongue'</span><span class=\"p\">]:</span>\n <span class=\"n\">key</span> <span class=\"o\">=</span> <span class=\"n\">start</span> <span class=\"o\">+</span> <span class=\"s1\">'-'</span> <span class=\"o\">+</span> <span class=\"n\">end</span>\n <span class=\"n\">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\">'snake-tiles/'</span> <span class=\"o\">+</span> <span class=\"n\">key</span> <span class=\"o\">+</span> <span class=\"s1\">'.png'</span><span class=\"p\">)</span>\n <span class=\"n\">snake_tiles</span><span class=\"p\">[</span><span class=\"n\">key</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">image</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\">tile</span> <span class=\"o\">=</span> <span class=\"n\">snake_tiles</span><span class=\"p\">[</span><span class=\"s1\">'end-end'</span><span class=\"p\">]</span>\n <span class=\"n\">tile</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,\nbudeme chtít vybrat vždycky ten správný.</p>\n<p>Jak na to?\nPodle čeho ho vybrat?</p>\n<p>Obrázky s kousky hada jsou pojmenovány\n<code><var>odkud</var>-kam.png</code>.\nTo není náhoda – ukazuje to, co potřebuješ vědět, abys mohla ten správný\nkousek vybrat.</p>\n<p>Když máš hada podle následujícího obrázku, na políčko (3, 2) patří\nkousek, na kterém had „leze“ zleva nahoru – tedy <code>left-top.png</code></p>\n<p><span class=\"figure\"><a href=\"/2019/brno-podzim-snake/snake/drawing/static/tile-selection.svg\"><img src=\"/2019/brno-podzim-snake/snake/drawing/static/tile-selection.svg\" alt=\"Had na „šachovnici“ se souřadnicemi. Políčko (3, 2) je zvýrazněné a vedou z něj šipky doleva a nahoru, kudy had pokračuje.\"></a></span></p>\n<p>Pro každé z políček budeš potřebovat zjistit, odkud a kam na něm had leze –\ntedy směr k <em>předchozí</em> a <em>následující</em> souřadnici.</p>\n<p>Potřebuješ pro <em>každé políčko</em> hada zjistit</p>\n<ul>\n<li><var>x</var>-ovou a <var>y</var>-ovou souřadnici políčka</li>\n<li>směr k <em>předchozímu</em> a <em>následujícímu</em> políčku</li>\n</ul>\n<p>Do programu se pak dají hodnoty zadat nějak takto:</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> <span class=\"c1\"># čím bude cyklus procházet? Samotným self.snake?</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\">before</span> <span class=\"o\">=</span> <span class=\"o\">...</span> <span class=\"c1\"># Směr k předchozímu políčku ('left' nebo 'top' nebo ...)</span>\n <span class=\"n\">after</span> <span class=\"o\">=</span> <span class=\"o\">...</span> <span class=\"c1\"># Směr k následujícímu políčku </span>\n\n <span class=\"n\">snake_tiles</span><span class=\"p\">[</span><span class=\"n\">before</span> <span class=\"o\">+</span> <span class=\"s1\">'-'</span> <span class=\"o\">+</span> <span class=\"n\">after</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>Toto je <strong>těžký úkol</strong>.\nI když všechny potřebné informace a nástroje k tomu teď teoreticky znáš,\nje potřeba je správným způsobem poskládat dohromady.\nTohle skládání dohromady, <em>návrh algoritmů</em>, je nejsložitější programátorská \ndisciplína.</p>\n<p>Zkus 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š.\nOdměnou za vyřešení 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 <a href=\"/2019/brno-podzim-snake/snake/logic/\">psaní logiky hry</a> s housenkou.</p>\n<p>Nebo se <a href=\"/2019/brno-podzim-snake/snake/tile-selection/\">necháš poddat</a>?</p>\n\n\n " } } }