Dnes si ukážeme, jak s Pythonem napsat grafickou aplikaci.
Použijeme knihovnu, která není zabudovaná přímo
v Pythonu (podobně jako pytest, který používáme na testování).
Musíme si ji nejdřív nainstalovat a na to použijeme
v zapnutém virtualenvu modul pip
–
konkrétně příkaz python -m pip install pyglet
.
U mě vypadá instalace nějak takto:
(venv)$ python -m pip install pyglet
Collecting pyglet
Downloading pyglet-1.2.4-py3-none-any.whl (964kB)
Installing collected packages: pyglet
Successfully installed pyglet-1.2.4
Máš-li nainstalováno, zkus napsat a spustit následující program. Mělo by se objevit černé okýnko:
import pyglet
window = pyglet.window.Window()
pyglet.app.run()
print('Hotovo!')
Jestli okýnko není černé ale je v něm nějaký „nepořádek“, představuj si zatím, že černé je. Stává se to hlavně na počítačích s Mac OS a některými druhy Linuxu. Než do okýnka začneme kreslit obrázky, nepořádek uklidíme.
Hotovo? Pojďme si vysvětlit, co se tu vlastně děje.
Podívejme se ještě jednou, jak zhruba vypadá hlavní program pro Piškvorky, který jsme napsaly na projektech. V komentářích je napsané, co která část kódu dělá:
def piskvorky1d():
pole = '-' * 20 # Příprava hry
while True: # Pořád dokola:
pole = tah_hrace(pole) # 1. Zeptej se na tah
if vyhodnot(pole) != '-': # 2. Zpracuj tah
break
print(pole) # 3. Vypiš stav hry
# A znova:
pole = tah_pocitace(pole) # 1. Zeptej se na tah
if vyhodnot(pole) != '-': # 2. Zpracuj tah
break
print(pole) # 3. Vypiš stav hry
V tomhle programu máme dva druhy akcí, které se pravidelně střídají. Jakmile taková akce nastane, ať vstup od člověka nebo od počítače, tak se zpracuje a výsledný stav se oznámí.
Podobnou strukturu „reakcí“ jsme použily už dřív, třeba u hry kámen-nůžky-papír:
A podobně funguje většina programů, které nějakým způsobem reagují na vstup od uživatele nebo i na jiné události.
Webový server čeká na požadavek (angl. request) o webovou stránku. Když nějaký přijme, zpracuje ho (např. přečte příslušnou stránku z disku) a jako výstup pošle odpověď.
Složitější programy reagují na spoustu druhů událostí, ne jen na „požadavek“ nebo „tah hráče“/„tah počítače“. Co se stane ve „vyhodnocení vstupu“ pak závisí na druhu události.
Webový prohlížeč čeká na kliknutí myši nebo stisk klávesy a zachová se podle něj – třeba pošle přes Internet požadavek vzdálenému serveru. A potom čeká na další akci. Může přijít odpověď od serveru, a až ta přijde, vykreslí příslušnou stránku na obrazovku. Nebo může uživatel zmáčknout „STOP“ a požadavek se zruší.
Textový editor čeká na různé druhy vstupu z klávesnice či myši a každý musí nějak zpracovat.
Prostě, podobná struktura programu – smyčka která načte vstup, zpracuje ho a vyprodukuje výstup – je velice užitečná. Říká se jí smyčka událostí (angl. event loop) a programy na ní postavené jsou řízené událostmi (angl. event-driven).
Programátoři jsou líní. Když je něco užitečné pro více programů, nebývá zvykem, že to každý programátor v každém programu opakuje. Napíše se to jednou a dobře, zabalí se to jako tzv. knihovna (angl. library) a ostatní to pak můžou používat.
Jedna z takových knihoven je Pyglet. Obsahuje kromě smyčky událostí taky funkce na vykreslování 2D grafiky (pomocí jiné knihovny zvané OpenGL) nebo třeba načítání událostí z klávesnice a myši.
Pojďme se vrátit k prográmku, který ukazuje okno:
import pyglet
window = pyglet.window.Window()
pyglet.app.run()
print('Hotovo!')
Celá smyčka událostí se skrývá ve funkci pyglet.app.run()
.
Načtení vstupu (např. z klávesnice) dělá Pyglet sám,
ale jejich zpracování a vykreslení výsledků
už je pro každý program jiné, takže si je budeš muset
naprogramovat sama.
Zatím pro nás Pyglet zpracovává jen dvě události:
zavření okna (tlačítkem „✕“, které k okýnkům přidává
operační systém) a stisk klávesy Esc,
který taky zavře okno.
Po zavření okna skončí smyčka událostí
(funkce pyglet.app.run()
)
a program může pokračovat.
Klávesa Esc není příliš zajímavá. Zkusme reagovat i na jiné klávesy.
V Pygletu se na události reaguje tak, že napíšeš
funkci a pak ji zaregistruješ (angl. register) – řekneš
Pygletu, aby ji vždy v pravý čas zavolal.
Události, která nastane, když uživatel píše na klávesnici,
se v Pygletu říká on_text
a zpracovává se takto:
import pyglet
window = pyglet.window.Window()
def zpracuj_text(text):
print(text)
window.push_handlers(on_text=zpracuj_text)
pyglet.app.run()
Co to dělá? window.push_handlers(on_text=zpracuj_text)
řekne Pygletu, že když uživatel něco napíše do našeho okna,
má Pyglet zavolat funkci zpracuj_text
.
Tahle funkce pak dostane jako argument text, který uživatel napsal.
Všimni si, že při registraci nepíšeme
zpracuj_text
se závorkami, ačkoli jsme si
kdysi
říkaly, že funkce se mají volat.
Vzpomínáš na tenhle příklad? Možná ti tehdy připadal zvláštní.
from math import sin
print(sin(1))
print(sin)
print(sin + 1)
Teď, když známe kromě čísel, řetězců a
True
/False
i soubory, seznamy,
n-tice a kdo ví jaké jiné typy, si můžeme říct,
že funkce je v Pythonu hodnota jako každá jiná.
Čísla se dají násobit, řetězce zapisovat do souboru,
ze souborů se dá číst – a funkce jsou zvláštní jen tím,
že se dají zavolat.
Než ale takovou funkci zavoláme, můžeme ji, tu samotnou
funkci, třeba přiřadit do proměnné:
vypis = print
vypis("Ahoj světe!")
nebo předat jako argument jiné funkci:
print(print)
No a funkce window.push_handlers
je přímo
dělaná na to, že jí předáš funkci.
Proč?
Pyglet nepotřebuje jeden výsledek funkce
zpracuj_text
– ten moc k ničemu není.
A navíc tu funkci teď ani nemůžeme zavolat; nemáme
vhodný argument text
.
Proto Pygletu dáme samotnou funkci, kterou bude sám
volat, kdykoli uživatel stiskne klávesu.
Ještě jednu událost zpracujme, než se přesuneme ke grafice.
Bude to takzvaný tik hodin (angl. clock tick). To je událost, která nastává pravidelně po nějakém čase.
Funkce pro tiky se registruje trochu jinak než on_text
:
import pyglet
window = pyglet.window.Window()
def tik(t):
print(t)
pyglet.clock.schedule_interval(tik, 1/30)
def zpracuj_text(text):
print(text)
window.push_handlers(on_text=zpracuj_text)
pyglet.app.run()
Co to dělá? pyglet.clock.schedule_interval(tik, 1/30)
řekne Pygletu, že má zavolat funkci tik
každou
třicetinu (1/30
) vteřiny.
A funkce tik
dostane jeden argument – kolik času
uplynulo od posledního zavolání.
Většinou to není přesně 1/30 vteřiny, ale něco víc.
Počítač má i jiné věci na práci, takže se k naší aplikaci
nemusí dostat hned; a taky Pythonu trvá nějakou tu
tisícinu vteřiny než zařídí samotné zavolání naší funkce.
A proč vlastně třicetina vteřiny?
Je to kvůli tomu, že potom budeme stavět animace.
Když se nám před očima vystřídá 30 obrázků za vteřinu,
mozek si je spojí a vznikne iluze plynulého pohybu.
Většina filmů používá jen 24 obrázků za vteřinu;
realistické 3D hry až 60.
Program, který vypisuje na terminál spoustu čísel, není asi zas tak zajímavý. Téma téhle stránky je ale grafika, tak se začněme od terminálu odpoutávat. Pojďme kreslit.
Najdi si na Internetu nějaký obrázek. Ne moc velký,
tak 3cm, ať je kolem něj v našem černém okýnku dost
místa, a nejlépe ve formátu PNG. Začni třeba na
téhle stránce.
Ale nevybírej obrázek, který je celý černý, protože by v našem černém okně
nebyl vidět.
Ulož si ho do adresáře, odkud spouštíš svůj pythonní
program. Já mám třeba obrázek hada v souboru had.png
.
Pak obrázek vykresli (použij jméno souboru se svým obrázkem):
import pyglet
window = pyglet.window.Window()
def tik(t):
print(t)
pyglet.clock.schedule_interval(tik, 1/30)
def zpracuj_text(text):
print(text)
obrazek = pyglet.image.load('had.png')
had = pyglet.sprite.Sprite(obrazek)
def vykresli():
window.clear()
had.draw()
window.push_handlers(
on_text=zpracuj_text,
on_draw=vykresli,
)
pyglet.app.run()
Povedlo se?
Vysvětleme si, co se tady děje:
obrazek = pyglet.image.load('had.png')
načte ze souboru obrázekhad = pyglet.sprite.Sprite(obrazek)
vytvoří speciální objekt Sprite,
který určuje, že tento obrázek chceme „posadit“
na určité místo v černém okýnku.
Když neuděláme nic dalšího, bude obrázek čekat v levém rohu.vykresli()
se stará o vykreslení okna – výstup našeho programu.
Volá se vždycky, když je potřeba okno překreslit –
například když okno minimalizuješ a pak vrátíš
nebo přesuneš částečně ven z obrazovky a pak dáš zase zpět.
A nebo když budeme něco animovat.Některé operační systémy si pamatují i obsah oken, které nejsou vidět, ale není radno na to spoléhat.
window.clear()
vyčistí okno – natře ho černou barvou a smaže
všechno, co v něm bylo předtím.Na spoustě počítačů tohle není potřeba. Ale je lepší psát programy tak, aby běžely správně kdekoli.
had.draw()
nakreslí obrázek pomocí předpřipraveného spritu had
.window.push_handlers(on_draw=vykresli)
zaregistruje funkci vykresli
–
řekne Pygletu, aby ji volal vždy, když je třeba.
push_handlers
takhle najednou.Jakékoli kreslení se musí dělat v rámci kreslící funkce,
kterou Pyglet volá z on_draw
.
Jinde funkce jako clear
a draw
nebudou fungovat správně.
Pojď si teď se Spritem trochu pohrát.
Do funkce zpracuj_text
dej místo printu tento příkaz:
def zpracuj_text(text):
had.x = 150
Náš Sprite má atribut (angl. attribute)
x
, který určuje jeho x-ovou souřadnici –
jak moc je vpravo od okraje okna.
Tenhle atribut se dá nastavit, jak budeš chtít – nejčastěji
v reakci na nějakou událost, ale často se nastavuje
i na začátku programu.
Zajímavé je zkusit k x
něco přičíst při každém tiknutí hodin.
Dokážeš předpovědět, co udělá tenhle kód?
def tik(t):
had.x = had.x + t * 20
Nebojíš-li se matematiky, naimportuj math
a nech obrázek, ať se pohybuje podle nějaké funkce:
def tik(t):
had.x = had.x + t * 20
had.y = 20 + 20 * math.sin(had.x / 5)
Co se stane, když začneš měnit ta čísla?
Co se stane, když zkusíš podobně nastavovat atribut rotation
?
Pyglet umí kromě opakovaného „tikání“ zavolat funkci jednorázově, za určitou dobu.
Stáhni si (nebo vytvoř) druhý obrázek. Já mám druhého hada, tentokrát s trochu natočenou hlavou a ocasem.
Až budeš mít obrázek v adresáři s programem,
přidej těsně před pyglet.app.run()
tenhle kus kódu:
obrazek2 = pyglet.image.load('had2.png')
def zmen(t):
had.image = obrazek2
pyglet.clock.schedule_once(zmen, 1)
Volání schedule_once(zmen, 1)
říká Pygletu,
že za jednu vteřinu má zavolat funkci zmen
.
A funkce změní obrázek – stejně jako se předtím měnily
souřadnice.
schedule_once
se dá volat i v rámci obsluhy jiné události. Zkus funkci zmen
nahradit tímhle:
def zmen(t):
had.image = obrazek2
pyglet.clock.schedule_once(zmen_zpatky, 0.2)
def zmen_zpatky(t):
had.image = obrazek
pyglet.clock.schedule_once(zmen, 0.2)
Poslední věc, na kterou se tady naučíme reagovat, je klikání.
Těsně před window.push_handlers
napiš funkci:
def klik(x, y, tlacitko, mod):
had.x = x
had.y = y
… a pak v push_handlers
ji zaregistruj
pomocí řádku on_mouse_press=klik,
.
Co znamená který argument, to zkus zjistit sama.
Nápověda
print
!
Kdykoliv budeš chtít zjistit nějakou hodnotu, prostě si ji vypiš.Koukám že kódu už je dnes tak akorát na ukončení lekce:
import math
import pyglet
window = pyglet.window.Window()
def tik(t):
had.x = had.x + t * 20
pyglet.clock.schedule_interval(tik, 1/30)
def zpracuj_text(text):
had.x = 150
had.rotation = had.rotation + 10
obrazek = pyglet.image.load('had.png')
had = pyglet.sprite.Sprite(obrazek, x=10, y=10)
def vykresli():
window.clear()
had.draw()
def klik(x, y, tlacitko, mod):
print(tlacitko, mod)
had.x = x
had.y = y
window.push_handlers(
on_text=zpracuj_text,
on_draw=vykresli,
on_mouse_press=klik,
)
obrazek2 = pyglet.image.load('had2.png')
def zmen(t):
had.image = obrazek2
pyglet.clock.schedule_once(zmen_zpatky, 0.2)
def zmen_zpatky(t):
had.image = obrazek
pyglet.clock.schedule_once(zmen, 0.2)
pyglet.clock.schedule_once(zmen, 0.2)
pyglet.app.run()
Se vstupem z klávesnice a myši, časováním a vykreslováním Spritu si vystačíš u leckteré hry nebo grafické aplikace.
Až budeš nějakou hru dělat, zkus udržovat stav aplikace v seznamech a n-ticích (případně slovnících a třídách, které se naučíme později). Jedna funkce by měla umět takový stav vykreslit a jiné s ním pak budou manipulovat. Tyhle dvě sady funkcí můžeš mít i v jiných souborech, aby se nezapletly dohromady.
Zajímá-li tě toto téma, zkus si zahrát přiloženou hru Pong, která ukazuje některé další možnosti Pygletu: psaní textu, kreslení obdélníků a obsluhu jednotlivých kláves (např. šipek). Na první pohled může její kód vypadat složitě, ale zkus si k němu sednout a s pomocí komentářů ho pochopit. Kdyby komentáře nestačily, jsou k Pongu připravené i podrobné materiály.
To, co jsme tu probraly a pár věcí navíc, je shrnuto v taháku na Pyglet, který si můžeš stáhnout a vytisknout.
A chceš-li se do Pygletu ponořit hlouběji, existuje pro něj dokumentace. Nebude-li ti v ní něco jasné, zeptej se!
{ "data": { "sessionMaterial": { "id": "session-material:2017/pyladies-praha-jaro:pyglet:0", "title": "Grafika", "html": "\n \n \n\n <h1>Grafika</h1>\n<p>Dnes si ukážeme, jak s Pythonem napsat grafickou aplikaci.</p>\n<p>Použijeme knihovnu, která není zabudovaná přímo\nv Pythonu (podobně jako pytest, který používáme na testování).\nMusíme si ji nejdřív nainstalovat a na to použijeme\nv zapnutém virtualenvu modul <code>pip</code> –\nkonkrétně příkaz <code>python -m pip install pyglet</code>.\nU mě vypadá instalace nějak takto:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">(venv)$ </span>python -m pip install pyglet\n<span class=\"go\">Collecting pyglet</span>\n<span class=\"go\"> Downloading pyglet-1.2.4-py3-none-any.whl (964kB)</span>\n<span class=\"go\">Installing collected packages: pyglet</span>\n<span class=\"go\">Successfully installed pyglet-1.2.4</span>\n</pre></div><p>Máš-li nainstalováno, zkus napsat a spustit\nnásledující program. Mělo by se objevit černé\nokýnko:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">pyglet</span>\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<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<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'Hotovo!'</span><span class=\"p\">)</span>\n</pre></div><div class=\"admonition note\"><p>Jestli okýnko není černé ale je v něm nějaký\n„nepořádek“, představuj si zatím, že černé je.\nStává se to hlavně na počítačích s Mac OS a některými\ndruhy Linuxu.\nNež do okýnka začneme kreslit obrázky, nepořádek\nuklidíme.</p>\n</div><p>Hotovo? Pojďme si vysvětlit, co se tu vlastně děje.</p>\n<h2>Interaktivní programy</h2>\n<p>Podívejme se ještě jednou, jak zhruba vypadá hlavní\nprogram pro Piškvorky, který jsme napsaly\nna projektech.\nV komentářích je napsané, co která část kódu dělá:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">piskvorky1d</span><span class=\"p\">():</span>\n <span class=\"n\">pole</span> <span class=\"o\">=</span> <span class=\"s1\">'-'</span> <span class=\"o\">*</span> <span class=\"mi\">20</span> <span class=\"c1\"># Příprava hry</span>\n <span class=\"k\">while</span> <span class=\"bp\">True</span><span class=\"p\">:</span> <span class=\"c1\"># Pořád dokola:</span>\n <span class=\"n\">pole</span> <span class=\"o\">=</span> <span class=\"n\">tah_hrace</span><span class=\"p\">(</span><span class=\"n\">pole</span><span class=\"p\">)</span> <span class=\"c1\"># 1. Zeptej se na tah</span>\n <span class=\"k\">if</span> <span class=\"n\">vyhodnot</span><span class=\"p\">(</span><span class=\"n\">pole</span><span class=\"p\">)</span> <span class=\"o\">!=</span> <span class=\"s1\">'-'</span><span class=\"p\">:</span> <span class=\"c1\"># 2. Zpracuj tah</span>\n <span class=\"k\">break</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">pole</span><span class=\"p\">)</span> <span class=\"c1\"># 3. Vypiš stav hry</span>\n\n <span class=\"c1\"># A znova:</span>\n <span class=\"n\">pole</span> <span class=\"o\">=</span> <span class=\"n\">tah_pocitace</span><span class=\"p\">(</span><span class=\"n\">pole</span><span class=\"p\">)</span> <span class=\"c1\"># 1. Zeptej se na tah</span>\n <span class=\"k\">if</span> <span class=\"n\">vyhodnot</span><span class=\"p\">(</span><span class=\"n\">pole</span><span class=\"p\">)</span> <span class=\"o\">!=</span> <span class=\"s1\">'-'</span><span class=\"p\">:</span> <span class=\"c1\"># 2. Zpracuj tah</span>\n <span class=\"k\">break</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">pole</span><span class=\"p\">)</span> <span class=\"c1\"># 3. Vypiš stav hry</span>\n</pre></div><p>V tomhle programu máme dva druhy akcí, které se pravidelně střídají.\nJakmile taková akce nastane, ať vstup od člověka nebo\nod počítače, tak se zpracuje a výsledný stav se oznámí.</p>\n<p>Podobnou strukturu „reakcí“ jsme použily už dřív,\ntřeba u hry kámen-nůžky-papír:</p>\n<ul>\n<li>Nějaká příprava</li>\n<li>Dokud program nemá skončit:<ul>\n<li>Načti vstup</li>\n<li>Nějak ten vstup vyhodnoť</li>\n<li>Vypiš výstup</li>\n</ul>\n</li>\n</ul>\n<p>A podobně funguje většina programů, které nějakým\nzpůsobem reagují na vstup od uživatele nebo i na jiné\nudálosti.</p>\n<p>Webový server čeká na <em>požadavek</em> (angl. <em>request</em>)\no webovou stránku. Když nějaký přijme, zpracuje ho\n(např. přečte příslušnou stránku z disku)\na jako výstup pošle odpověď.</p>\n<p>Složitější programy reagují na spoustu druhů událostí,\nne jen na „požadavek“ nebo „tah hráče“/„tah počítače“.\nCo se stane ve „vyhodnocení vstupu“ pak závisí\nna druhu události.</p>\n<p>Webový prohlížeč čeká na kliknutí myši nebo stisk klávesy\na zachová se podle něj – třeba pošle přes Internet\npožadavek vzdálenému serveru.\nA potom čeká na další akci. Může přijít odpověď od\nserveru, a až ta přijde, vykreslí příslušnou stránku\nna obrazovku. Nebo může uživatel zmáčknout „STOP“\na požadavek se zruší.</p>\n<p>Textový editor čeká na různé druhy vstupu z klávesnice\nči myši a každý musí nějak zpracovat.</p>\n<p>Prostě, podobná struktura programu – smyčka která\nnačte vstup, zpracuje ho a vyprodukuje výstup – je velice užitečná.\nŘíká se jí <em>smyčka událostí</em> (angl. <em>event loop</em>)\na programy na ní postavené jsou\n<em>řízené událostmi</em> (angl. <em>event-driven</em>).</p>\n<p>Programátoři jsou líní.\nKdyž je něco užitečné pro více programů, nebývá\nzvykem, že to každý programátor v každém programu opakuje.\nNapíše se to jednou a dobře, zabalí se to jako tzv.\n<em>knihovna</em> (angl. <em>library</em>)\na ostatní to pak můžou používat.</p>\n<h2>Pyglet 🐷</h2>\n<p>Jedna z takových knihoven je Pyglet.\nObsahuje kromě smyčky událostí taky funkce na\nvykreslování 2D grafiky (pomocí jiné knihovny zvané\nOpenGL) nebo třeba načítání událostí z klávesnice a myši.</p>\n<p>Pojďme se vrátit k prográmku, který ukazuje okno:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">pyglet</span>\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<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<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'Hotovo!'</span><span class=\"p\">)</span>\n</pre></div><p>Celá smyčka událostí se skrývá ve funkci <code>pyglet.app.run()</code>.\nNačtení vstupu (např. z klávesnice) dělá Pyglet sám,\nale jejich zpracování a vykreslení výsledků\nuž je pro každý program jiné, takže si je budeš muset\nnaprogramovat sama.</p>\n<p>Zatím pro nás Pyglet zpracovává jen dvě události:\nzavření okna (tlačítkem „✕“, které k okýnkům přidává\noperační systém) a stisk klávesy <kbd>Esc</kbd>,\nkterý taky zavře okno.\nPo zavření okna skončí smyčka událostí\n(funkce <code>pyglet.app.run()</code>)\na program může pokračovat.</p>\n<h2>Text</h2>\n<p>Klávesa <kbd>Esc</kbd> není příliš zajímavá.\nZkusme reagovat i na jiné klávesy.</p>\n<p>V Pygletu se na události reaguje tak, že napíšeš\nfunkci a pak ji <em>zaregistruješ</em> (angl. <em>register</em>) – řekneš\nPygletu, aby ji vždy v pravý čas zavolal.\nUdálosti, která nastane, když uživatel píše na klávesnici,\nse v Pygletu říká <code>on_text</code> a zpracovává se takto:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">pyglet</span>\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=\"k\">def</span> <span class=\"nf\">zpracuj_text</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">):</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">)</span>\n\n<span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">push_handlers</span><span class=\"p\">(</span><span class=\"n\">on_text</span><span class=\"o\">=</span><span class=\"n\">zpracuj_text</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>Co to dělá? <code>window.push_handlers(on_text=zpracuj_text)</code>\nřekne Pygletu, že když uživatel něco napíše do našeho okna,\nmá Pyglet zavolat funkci <code>zpracuj_text</code>.\nTahle funkce pak dostane jako argument text, který uživatel napsal.</p>\n<p>Všimni si, že při registraci nepíšeme\n<code>zpracuj_text</code> se závorkami, ačkoli jsme si\n<a href=\"/2017/pyladies-praha-jaro/beginners/functions/\">kdysi</a>\nříkaly, že funkce se mají volat.\nVzpomínáš na tenhle příklad? Možná ti tehdy připadal zvláštní.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">math</span> <span class=\"kn\">import</span> <span class=\"n\">sin</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">sin</span><span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">))</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">sin</span><span class=\"p\">)</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">sin</span> <span class=\"o\">+</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n</pre></div><p>Teď, když známe kromě čísel, řetězců a\n<code>True</code>/<code>False</code> i soubory, seznamy,\n<var>n</var>-tice a kdo ví jaké jiné typy, si můžeme říct,\nže funkce je v Pythonu hodnota jako každá jiná.\nČísla se dají násobit, řetězce zapisovat do souboru,\nze souborů se dá číst – a funkce jsou zvláštní jen tím,\nže se dají zavolat.\nNež ale takovou funkci zavoláme, můžeme ji, tu samotnou\nfunkci, třeba přiřadit do proměnné:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">vypis</span> <span class=\"o\">=</span> <span class=\"k\">print</span>\n<span class=\"n\">vypis</span><span class=\"p\">(</span><span class=\"s2\">"Ahoj světe!"</span><span class=\"p\">)</span>\n</pre></div><p>nebo předat jako argument jiné funkci:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"k\">print</span><span class=\"p\">)</span>\n</pre></div><p>No a funkce <code>window.push_handlers</code> je přímo\ndělaná na to, že jí předáš funkci.\nProč?\nPyglet nepotřebuje jeden výsledek funkce\n<code>zpracuj_text</code> – ten moc k ničemu není.\nA navíc tu funkci teď ani nemůžeme zavolat; nemáme\nvhodný argument <code>text</code>.\nProto Pygletu dáme samotnou funkci, kterou bude sám\nvolat, kdykoli uživatel stiskne klávesu.</p>\n<h2>Čas ⏲</h2>\n<p>Ještě jednu událost zpracujme, než se přesuneme ke grafice.</p>\n<p>Bude to takzvaný <em>tik</em> hodin\n(angl. <em>clock tick</em>).\nTo je událost, která nastává pravidelně po nějakém čase.</p>\n<p>Funkce pro tiky se registruje trochu jinak než <code>on_text</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">pyglet</span>\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=\"k\">def</span> <span class=\"nf\">tik</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">)</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">clock</span><span class=\"o\">.</span><span class=\"n\">schedule_interval</span><span class=\"p\">(</span><span class=\"n\">tik</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"o\">/</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">zpracuj_text</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">):</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">)</span>\n\n<span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">push_handlers</span><span class=\"p\">(</span><span class=\"n\">on_text</span><span class=\"o\">=</span><span class=\"n\">zpracuj_text</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>Co to dělá? <code>pyglet.clock.schedule_interval(tik, 1/30)</code>\nřekne Pygletu, že má zavolat funkci <code>tik</code> každou\ntřicetinu (<code>1/30</code>) vteřiny.</p>\n<p>A funkce <code>tik</code> dostane jeden argument – kolik času\nuplynulo od posledního zavolání.\nVětšinou to není přesně 1/30 vteřiny, ale něco víc.\nPočítač má i jiné věci na práci, takže se k naší aplikaci\nnemusí dostat hned; a taky Pythonu trvá nějakou tu\ntisícinu vteřiny než zařídí samotné zavolání naší funkce.</p>\n<div class=\"admonition note\"><p>A proč vlastně třicetina vteřiny?\nJe to kvůli tomu, že potom budeme stavět animace.\nKdyž se nám před očima vystřídá 30 obrázků za vteřinu,\nmozek si je spojí a vznikne iluze plynulého pohybu.\n<br>\nVětšina filmů používá jen 24 obrázků za vteřinu;\nrealistické 3D hry až 60.</p>\n</div><h2>Vykreslování 🖌</h2>\n<p><img src=\"/2017/pyladies-praha-jaro/intro/pyglet/static/had.png\" alt style=\"display:block;float:right;\"></p>\n<p>Program, který vypisuje na terminál spoustu čísel,\nnení asi zas tak zajímavý.\nTéma téhle stránky je ale grafika, tak se začněme od\nterminálu odpoutávat. Pojďme kreslit.</p>\n<p>Najdi si na Internetu nějaký obrázek. Ne moc velký,\ntak 3cm, ať je kolem něj v našem černém okýnku dost\nmísta, a nejlépe ve formátu PNG. Začni třeba na\n<a href=\"https://www.google.cz/search?tbs=ift:png&tbm=isch&q=snake+icon\">téhle stránce</a>.\nAle nevybírej obrázek, který je celý černý, protože by v našem černém okně\nnebyl vidět.\nUlož si ho do adresáře, odkud spouštíš svůj pythonní\nprogram. Já mám třeba obrázek hada v souboru <code>had.png</code>.</p>\n<p>Pak obrázek vykresli (použij jméno souboru se svým obrázkem):</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">pyglet</span>\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=\"k\">def</span> <span class=\"nf\">tik</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">)</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">clock</span><span class=\"o\">.</span><span class=\"n\">schedule_interval</span><span class=\"p\">(</span><span class=\"n\">tik</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"o\">/</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">zpracuj_text</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">):</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">)</span>\n\n<span class=\"n\">obrazek</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\">'had.png'</span><span class=\"p\">)</span>\n<span class=\"n\">had</span> <span class=\"o\">=</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">sprite</span><span class=\"o\">.</span><span class=\"n\">Sprite</span><span class=\"p\">(</span><span class=\"n\">obrazek</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">vykresli</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\">had</span><span class=\"o\">.</span><span class=\"n\">draw</span><span class=\"p\">()</span>\n\n<span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">push_handlers</span><span class=\"p\">(</span>\n <span class=\"n\">on_text</span><span class=\"o\">=</span><span class=\"n\">zpracuj_text</span><span class=\"p\">,</span>\n <span class=\"n\">on_draw</span><span class=\"o\">=</span><span class=\"n\">vykresli</span><span class=\"p\">,</span>\n<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>Povedlo se?</p>\n<p>Vysvětleme si, co se tady děje:</p>\n<ul>\n<li><code>obrazek = pyglet.image.load('had.png')</code> načte ze souboru obrázek</li>\n<li><code>had = pyglet.sprite.Sprite(obrazek)</code>\nvytvoří speciální objekt <a href=\"https://cs.wikipedia.org/wiki/Sprite_%28po%C4%8D%C3%ADta%C4%8Dov%C3%A1_grafika%29\">Sprite</a>,\nkterý určuje, že tento obrázek chceme „posadit“\nna určité místo v černém okýnku.\nKdyž neuděláme nic dalšího, bude obrázek čekat v levém rohu.</li>\n<li>Funkce <code>vykresli()</code> se stará o vykreslení okna – výstup našeho programu.\nVolá se vždycky, když je potřeba okno překreslit –\nnapříklad když okno minimalizuješ a pak vrátíš\nnebo přesuneš částečně ven z obrazovky a pak dáš zase zpět.\nA nebo když budeme něco animovat.</li>\n</ul>\n<div class=\"admonition note\"><p>Některé operační systémy si pamatují i obsah oken,\nkteré nejsou vidět, ale není radno na to spoléhat.</p>\n</div><ul>\n<li><code>window.clear()</code> vyčistí okno – natře ho černou barvou a smaže\nvšechno, co v něm bylo předtím.</li>\n</ul>\n<div class=\"admonition note\"><p>Na spoustě počítačů tohle není potřeba.\nAle je lepší psát programy tak, aby\nběžely správně kdekoli.</p>\n</div><ul>\n<li><code>had.draw()</code> nakreslí obrázek pomocí předpřipraveného <em>spritu</em> <code>had</code>.</li>\n<li><code>window.push_handlers(on_draw=vykresli)</code> zaregistruje funkci <code>vykresli</code> –\nřekne Pygletu, aby ji volal vždy, když je třeba.\n<br>\nKdyž potřebuješ zaregistrovat pro jedno okno\nvíc funkcí na obsluhu událostí,\ndají se dát funkci <code>push_handlers</code>\ntakhle najednou.</li>\n</ul>\n<p>Jakékoli kreslení se <em>musí</em> dělat v rámci kreslící funkce,\nkterou Pyglet volá z <code>on_draw</code>.\nJinde funkce jako <code>clear</code> a <code>draw</code> nebudou fungovat správně.</p>\n<h2>Animace</h2>\n<p>Pojď si teď se Spritem trochu pohrát.</p>\n<p>Do funkce <code>zpracuj_text</code> dej místo printu tento příkaz:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">zpracuj_text</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"mi\">150</span>\n</pre></div><p>Náš Sprite má <em>atribut</em> (angl. <em>attribute</em>)\n<code>x</code>, který určuje jeho <var>x</var>-ovou souřadnici –\njak moc je vpravo od okraje okna.\nTenhle atribut se dá nastavit, jak budeš chtít – nejčastěji\nv reakci na nějakou událost, ale často se nastavuje\ni na začátku programu.</p>\n<p>Zajímavé je zkusit k <code>x</code> něco přičíst při každém tiknutí hodin.\nDokážeš předpovědět, co udělá tenhle kód?</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">tik</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">+</span> <span class=\"n\">t</span> <span class=\"o\">*</span> <span class=\"mi\">20</span>\n</pre></div><p>Nebojíš-li se matematiky, naimportuj <code>math</code>\na nech obrázek, ať se pohybuje podle nějaké funkce:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">tik</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">+</span> <span class=\"n\">t</span> <span class=\"o\">*</span> <span class=\"mi\">20</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">y</span> <span class=\"o\">=</span> <span class=\"mi\">20</span> <span class=\"o\">+</span> <span class=\"mi\">20</span> <span class=\"o\">*</span> <span class=\"n\">math</span><span class=\"o\">.</span><span class=\"n\">sin</span><span class=\"p\">(</span><span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">/</span> <span class=\"mi\">5</span><span class=\"p\">)</span>\n</pre></div><p>Co se stane, když začneš měnit ta čísla?</p>\n<p>Co se stane, když zkusíš podobně nastavovat atribut <code>rotation</code>?</p>\n<h2>Zavolej později</h2>\n<p><img src=\"/2017/pyladies-praha-jaro/intro/pyglet/static/had2.png\" alt style=\"display:block;float:right;\"></p>\n<p>Pyglet umí kromě opakovaného „tikání“ zavolat funkci\njednorázově, za určitou dobu.</p>\n<p>Stáhni si (nebo vytvoř) druhý obrázek. Já mám druhého\nhada, tentokrát s trochu natočenou hlavou a ocasem.</p>\n<p>Až budeš mít obrázek v adresáři s programem,\npřidej těsně před <code>pyglet.app.run()</code> tenhle kus kódu:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">obrazek2</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\">'had2.png'</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">zmen</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">image</span> <span class=\"o\">=</span> <span class=\"n\">obrazek2</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">clock</span><span class=\"o\">.</span><span class=\"n\">schedule_once</span><span class=\"p\">(</span><span class=\"n\">zmen</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n</pre></div><p>Volání <code>schedule_once(zmen, 1)</code> říká Pygletu,\nže za jednu vteřinu má zavolat funkci <code>zmen</code>.\nA funkce změní obrázek – stejně jako se předtím měnily\nsouřadnice.</p>\n<p><code>schedule_once</code> se dá volat i v rámci obsluhy jiné události. Zkus funkci <code>zmen</code>\nnahradit tímhle:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">zmen</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">image</span> <span class=\"o\">=</span> <span class=\"n\">obrazek2</span>\n <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">clock</span><span class=\"o\">.</span><span class=\"n\">schedule_once</span><span class=\"p\">(</span><span class=\"n\">zmen_zpatky</span><span class=\"p\">,</span> <span class=\"mf\">0.2</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">zmen_zpatky</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">image</span> <span class=\"o\">=</span> <span class=\"n\">obrazek</span>\n <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">clock</span><span class=\"o\">.</span><span class=\"n\">schedule_once</span><span class=\"p\">(</span><span class=\"n\">zmen</span><span class=\"p\">,</span> <span class=\"mf\">0.2</span><span class=\"p\">)</span>\n</pre></div><h2>Klik 🐭</h2>\n<p>Poslední věc, na kterou se tady naučíme reagovat, je klikání.\nTěsně před <code>window.push_handlers</code> napiš funkci:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">klik</span><span class=\"p\">(</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">,</span> <span class=\"n\">tlacitko</span><span class=\"p\">,</span> <span class=\"n\">mod</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">x</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">y</span> <span class=\"o\">=</span> <span class=\"n\">y</span>\n</pre></div><p>… a pak v <code>push_handlers</code> ji zaregistruj\npomocí řádku <code>on_mouse_press=klik,</code>.</p>\n<p>Co znamená který argument, to zkus zjistit sama.</p>\n<div class=\"admonition note\"><p class=\"admonition-title\">Nápověda</p>\n<ul>\n<li>Dokud příkazovou řádku neopustíš úplně, bude fungovat <code>print</code>!\nKdykoliv budeš chtít zjistit nějakou hodnotu, prostě si ji vypiš.</li>\n<li>Kolik má myš tlačítek?</li>\n<li>Jak se projeví <kbd>Shift</kbd>+klik?</li>\n</ul>\n</div><h2>Pokračování příště</h2>\n<p>Koukám že kódu už je dnes tak akorát na ukončení lekce:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">math</span>\n\n<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=\"k\">def</span> <span class=\"nf\">tik</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">+</span> <span class=\"n\">t</span> <span class=\"o\">*</span> <span class=\"mi\">20</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">clock</span><span class=\"o\">.</span><span class=\"n\">schedule_interval</span><span class=\"p\">(</span><span class=\"n\">tik</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"o\">/</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">zpracuj_text</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"mi\">150</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">rotation</span> <span class=\"o\">=</span> <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">rotation</span> <span class=\"o\">+</span> <span class=\"mi\">10</span>\n\n<span class=\"n\">obrazek</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\">'had.png'</span><span class=\"p\">)</span>\n<span class=\"n\">had</span> <span class=\"o\">=</span> <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">sprite</span><span class=\"o\">.</span><span class=\"n\">Sprite</span><span class=\"p\">(</span><span class=\"n\">obrazek</span><span class=\"p\">,</span> <span class=\"n\">x</span><span class=\"o\">=</span><span class=\"mi\">10</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"o\">=</span><span class=\"mi\">10</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">vykresli</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\">had</span><span class=\"o\">.</span><span class=\"n\">draw</span><span class=\"p\">()</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">klik</span><span class=\"p\">(</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">,</span> <span class=\"n\">tlacitko</span><span class=\"p\">,</span> <span class=\"n\">mod</span><span class=\"p\">):</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">tlacitko</span><span class=\"p\">,</span> <span class=\"n\">mod</span><span class=\"p\">)</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">x</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">y</span> <span class=\"o\">=</span> <span class=\"n\">y</span>\n\n<span class=\"n\">window</span><span class=\"o\">.</span><span class=\"n\">push_handlers</span><span class=\"p\">(</span>\n <span class=\"n\">on_text</span><span class=\"o\">=</span><span class=\"n\">zpracuj_text</span><span class=\"p\">,</span>\n <span class=\"n\">on_draw</span><span class=\"o\">=</span><span class=\"n\">vykresli</span><span class=\"p\">,</span>\n <span class=\"n\">on_mouse_press</span><span class=\"o\">=</span><span class=\"n\">klik</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n\n<span class=\"n\">obrazek2</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\">'had2.png'</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">zmen</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">image</span> <span class=\"o\">=</span> <span class=\"n\">obrazek2</span>\n <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">clock</span><span class=\"o\">.</span><span class=\"n\">schedule_once</span><span class=\"p\">(</span><span class=\"n\">zmen_zpatky</span><span class=\"p\">,</span> <span class=\"mf\">0.2</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">zmen_zpatky</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">):</span>\n <span class=\"n\">had</span><span class=\"o\">.</span><span class=\"n\">image</span> <span class=\"o\">=</span> <span class=\"n\">obrazek</span>\n <span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">clock</span><span class=\"o\">.</span><span class=\"n\">schedule_once</span><span class=\"p\">(</span><span class=\"n\">zmen</span><span class=\"p\">,</span> <span class=\"mf\">0.2</span><span class=\"p\">)</span>\n\n<span class=\"n\">pyglet</span><span class=\"o\">.</span><span class=\"n\">clock</span><span class=\"o\">.</span><span class=\"n\">schedule_once</span><span class=\"p\">(</span><span class=\"n\">zmen</span><span class=\"p\">,</span> <span class=\"mf\">0.2</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>Se vstupem z klávesnice a myši, časováním a vykreslováním\nSpritu si vystačíš u leckteré hry nebo grafické aplikace.</p>\n<p>Až budeš nějakou hru dělat, zkus udržovat\nstav aplikace v seznamech a <var>n</var>-ticích (případně\nslovnících a třídách, které se naučíme později).\nJedna funkce by měla umět takový stav vykreslit a\njiné s ním pak budou manipulovat.\nTyhle dvě sady funkcí můžeš mít i v jiných souborech,\naby se nezapletly dohromady.</p>\n<p>Zajímá-li tě toto téma, zkus si zahrát přiloženou hru\n<a href=\"/2017/pyladies-praha-jaro/intro/pyglet/static/pong.py\">Pong</a>,\nkterá ukazuje některé další\nmožnosti Pygletu: psaní textu, kreslení obdélníků\na obsluhu jednotlivých kláves (např. šipek).\nNa první pohled může její kód vypadat složitě,\nale zkus si k němu sednout a s pomocí komentářů ho pochopit.\nKdyby komentáře nestačily, jsou k Pongu připravené\ni <a href=\"/2017/pyladies-praha-jaro/projects/pong/\">podrobné materiály</a>.</p>\n<p>To, co jsme tu probraly a pár věcí navíc,\nje shrnuto v <a href=\"https://pyvec.github.io/cheatsheets/pyglet/pyglet-basics-cs.pdf\">taháku na Pyglet</a>,\nkterý si můžeš stáhnout a vytisknout.</p>\n<p>A chceš-li se do Pygletu ponořit hlouběji,\nexistuje pro něj <a href=\"http://pyglet.readthedocs.org/en/latest/index.html\">dokumentace</a>.\nNebude-li ti v ní něco jasné, zeptej se!</p>\n\n\n " } } }