Obsah
1. První miniaplikace vytvořené v nástroji Pygame Zero (2.část)
2. Práce se vstupními zařízeními a animace
3. Kostra demonstračních příkladů – zobrazení spritu
4. Konstanty se jmény stisknutých kláves, popř. použitých modifikátorů
5. Tisk kódu stisknuté klávesy a modifikátoru(ů)
6. Ukončení aplikace zvolenou klávesou
7. Posun spritu s využitím kurzorových šipek
8. Posun spritu ve funkci update
9. Úplný zdrojový kód upraveného příkladu
10. Korektní reakce na stisk i puštění (uvolnění) klávesy
11. Úplný zdrojový kód upraveného příkladu
12. Posun spritu společně s kurzorem myši
13. Posun spritu po stisku libovolného tlačítka myši
14. Základy tvorby animací v Pygame Zero
15. Animovaný přesun spritu na pozici kurzoru myši
16. Pojmenované barvy podporované nástrojem Pygame Zero
17. Zobrazení pojmenovaných barev podporovaných nástrojem Pygame Zero
18. Relevantní funkce z knihovny Pygame
19. Repositář s demonstračními příklady
1. První miniaplikace vytvořené v nástroji Pygame Zero (2.část)
V předchozí části miniseriálu, v němž se zabýváme popisem možností nástroje Pygame Zero určeného pro výuku programování formou tvorby her a multimediálních aplikací, jsme se zmínili o základních třídách, které jsou v Pygame Zero deklarovány a které se používají při tvorbě aplikací (tyto třídy, resp. jejich balíčky není zapotřebí importovat – to je provedeno při inicializaci jednotlivých subsystémů Pygame Zero zcela automaticky). Taktéž jsme si řekli, že po inicializaci aplikace jsou opět zcela automaticky k dispozici některé instance těchto tříd. Týká se to především objektu screen představujícího (jediné) okno aplikace a dále o objekty používané při práci s rastrovými obrázky (pozadí aplikace, sprity atd.) a fonty – tyto takzvané zdroje (resource) jsou totiž automaticky hledány v adresářích „images“, popř. „fonts“. Podobně se bude pracovat, jak ostatně uvidíme dále, i se soubory s uloženými zvuky, popř. s hudbou. Pro krátké připomenutí si ještě jednou ukažme tabulku, v níž jsou vypsány třídy a jejich instance (tedy objekty) využívané v aplikacích založených na projektu Pygame Zero:
# | Třída | Instance | Stručný popis |
---|---|---|---|
1 | Screen | screen | obrazovka, přesněji řečeno okno, do kterého se vykresluje scéna hry/aplikace |
2 | Actor | reprezentuje takzvaný sprite | |
3 | Surface | screen.surface | vlastní plocha okna, do kterého se kreslí (odvozeno z Pygame) |
4 | SurfacePainter | screen.draw | pomocný objekt obsahující metody pro kreslení základní 2D entit |
5 | Rect, NoIntersect, ZRect | osově orientovaný obdélník používaný na více místech | |
6 | ImageLoader | images | všechny obrázky uložené v podadresáři „images“ |
7 | Sound | třída umožňující přehrávání zvuků | |
8 | SoundLoader | sounds | všechny nalezené zvukové soubory ve formátech WAV a .ogg (bude popsáno příště) |
9 | _MusicLoader | třída umožňující načítání hudby | |
10 | Music | music | všechny soubory s hudbou nalezené v podadresáři „music“ |
11 | Clock | clock | objekt umožňující plánování (načasování) provedení nějaké úlohy |
12 | Animation | třída podporující postupnou změnu stavu prakticky libovolného objektu Pygame Zero | |
13 | Keyboard | keyboard | atributy pro všechny klávesy nastavené na True či False podle stavu stisknutí |
14 | FontLoader | načítání fontů uložených v podadresáři „fonts“ |
2. Práce se vstupními zařízeními a animace
Dnes se zaměříme na dvě oblasti používané prakticky ve všech multimediálních aplikacích, resp. přesněji řečeno v interaktivních aplikacích. První z těchto oblastí je práce se vstupními zařízeními, což v praxi znamená práci s klávesnicí a myší, i když na tomto místě je dobré poznamenat, že knihovna Pygame, nad níž je Pygame Zero postavena, podporuje i další vstupní zařízení – různé herní ovladače atd. Zapomenout nesmíme ani na tvorbu animací, protože ty tvoří nedílnou součást prakticky všech multimediálních aplikací i her (ostatně i samotný pohyb hráče, popř. NPC v herním světě je mnohdy i poměrně složitě animován). Začneme popisem práce se vstupními zařízeními. Použijeme přitom kostru jednoduché aplikace, kterou budeme postupně rozšiřovat o další funkcionalitu. Tato aplikace bude zpočátku značně triviální – pouze se v ní zobrazí okno s pozadím vyplněným zadanou barvou a v tomto okně je navíc umístěn sprite, což je rastrový obrázek (s některými pixely průhlednými či poloprůhlednými), kterým je možné manipulovat – měnit jeho polohu atd.
Obrázek 1: Funkcionalita kostry demonstračního příkladu – sprite vykreslený přesně uprostřed obrazovky (resp. přesněji řečeno okna aplikace).
3. Kostra demonstračních příkladů – zobrazení spritu
Připomeňme si základní informace o spritech, které jsme si řekli již v úvodním článku: jedná se o grafické objekty představované rastrovými obrázky, kterými je možné po obrazovce pohybovat a v nejnovější verzi nástroje Pygame Zero dokonce i otáčet. Relativně snadno je možné implementovat i takzvanou detekci kolizí (collision detection) mezi jednotlivými sprity, popř. mezi spritem a nepohyblivými objekty umístěnými na obrazovce. Termín „sprite“ pochází z doby osmibitových herních konzolí i osmibitových domácích mikropočítačů, které mnohdy obsahovaly specializovaný hardware určený jak pro zobrazení pohyblivých spritů (nezávislých na takzvaném herním poli – playground), tak i pro detekci kolizí mezi sprity, popř. mezi spritem a barvami (resp. přesněji řečeno obarvenými pixely) v herním poli. Ovšem samotný termín „sprite“ může být v dnešní době trošku matoucí (zejména bez znalosti historie herní grafiky), takže se v nástroji Pygame Zero namísto toho používá název „actor“. A stejně je pojmenována i třída s definicí chování spritů.
Obrázek 2: Osm čtyřbarevných spritů zobrazených v režimu multi-color čipem VIC-II na počítači Commodore C64.
Kostra demonstračního příkladu, který budeme v rámci dalších kapitol postupně rozšiřovat, vypadá následovně:
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (240, 240) def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw()
Všechny části tohoto demonstračního příkladu již známe, takže jen ve stručnosti:
- Konstanty pojmenované WIDTH a HEIGHT jsou nástrojem Pygame Zero zpracovány a na jejich základě je vytvořeno okno aplikace se zadanými rozměry (specifikovanými v pixelech). Z tohoto důvodu je nutné použít přesně takto pojmenované konstanty.
- Vykreslení obsahu okna je řízeno z funkce nazvanédraw, která je (resp. jejíž jméno je) taktéž rozpoznáno a použito nástrojem Pygame Zero. Ovšem snadno poznáme, že tato funkce není volána opakovaně (postačuje do funkce přidat například jednoduché logování atd.), pouze ve chvíli, kdy je to nezbytně nutné pro překreslení scény.
- Obrazovka je vyplněna specifikovanou barvou. Tuto barvu je možné zadat buď pomocí jejího jména nebo jako trojici hodnot představujících barvové složky RGB (Red, Green, Blue). Jména podporovaných barev naleznete v samostatné kapitole, popř. na adrese https://pygame-zero.readthedocs.io/en/latest/colors_ref.html.
- Instance třídy Actor představuje sprite, který lze vykreslit na libovolné místo na obrazovce. Implicitně je bod 0, 0 spritu vztažen k jeho středu, takže pozicování spritu přesně do středu obrazovky je snadné (resp. přesněji řečeno může být střed posunut o jeden pixel v případě, kdy jeden z odpovídajících rozměrů je lichý a druhý sudý).
- Rastrový obrázek, který určuje způsob zobrazení spritu, je načten ze souboru uloženého v podadresáři „images“. Tento obrázek může obsahovat (a v našem případě skutečně i obsahuje) průhledné a poloprůhledné pixely, což je ostatně jedna z typických vlastností spritů – nemusí po vykreslení tvořit čtverec či obdélník – podporovaná již od poloviny sedmdesátých let minulého století.
Obrázek 3: Kdysi byly možnosti grafiky a dostupných příkazů ještě menší. Zde můžeme vidět monochromatický grafický režim známý pod označením GRAPHICS 8 podle příkazu, kterým se nastavoval v Atari Basicu. V tomto režimu bylo možné na jednom obrazovém řádku zobrazit 320 pixelů, u nichž se, podobně jako ve standardním textovém režimu, rozlišovala pouze intenzita barvy – barevný odstín byl pro pozadí i popředí totožný. Ve spodní části obrazovky se nachází čtyři volitelné textové řádky, ve kterých jsou vypsány příkazy pro zobrazení úsečky. Repertoár grafických příkazů byl minimální: výběr barvy kreslení příkazem COLOR, vykreslení bodu příkazem PLOT a nakreslení úsečky příkazem DRAWTO.
4. Konstanty se jmény stisknutých kláves popř. použitých modifikátorů
Konstanty reprezentující jména stisknutých (či naopak puštěných) kláves jsou uloženy ve formě atributů objektu keys. Jména těchto konstant v naprosté většině případů odpovídají stejně pojmenovaným klávesám. Prefix K_ odpovídá klávesám umístěným v numerickém bloku:
Konstanta | Konstanta | Konstanta | Konstanta |
---|---|---|---|
BACKSPACE | TAB | CLEAR | RETURN |
PAUSE | ESCAPE | SPACE | EXCLAIM |
QUOTEDBL | HASH | DOLLAR | AMPERSAND |
QUOTE | LEFTPAREN | RIGHTPAREN | ASTERISK |
PLUS | COMMA | MINUS | PERIOD |
SLASH | K0 | K1 | K2 |
K3 | K4 | K5 | K6 |
K7 | K8 | K9 | COLON |
SEMICOLON | LESS | EQUALS | GREATER |
QUESTION | AT | LEFTBRACKET | BACKSLASH |
RIGHTBRACKET | CARET | UNDERSCORE | BACKQUOTE |
A | B | C | D |
E | F | G | H |
I | J | K | L |
M | N | O | P |
Q | R | S | T |
U | V | W | X |
Y | Z | DELETE | KP0 |
KP1 | KP2 | KP3 | KP4 |
KP5 | KP6 | KP7 | KP8 |
KP9 | KP_PERIOD | KP_DIVIDE | KP_MULTIPLY |
KP_MINUS | KP_PLUS | KP_ENTER | KP_EQUALS |
UP | DOWN | RIGHT | LEFT |
INSERT | HOME | END | PAGEUP |
PAGEDOWN | F1 | F2 | F3 |
F4 | F5 | F6 | F7 |
F8 | F9 | F10 | F11 |
F12 | F13 | F14 | F15 |
NUMLOCK | CAPSLOCK | SCROLLOCK | RSHIFT |
LSHIFT | RCTRL | LCTRL | RALT |
LALT | RMETA | LMETA | LSUPER |
RSUPER | MODE | HELP | |
SYSREQ | BREAK | MENU | POWER |
EURO | LAST |
Klávesy lze stisknout (pustit) společně s nějakým modifikátorem či modifikátory. Hodnoty modifikátorů jsou uloženy jako atributy objektu keymods:
Jméno konstanty |
---|
LSHIFT |
RSHIFT |
SHIFT |
LCTRL |
RCTRL |
CTRL |
LALT |
RALT |
ALT |
LMETA |
RMETA |
META |
NUM |
CAPS |
MODE |
5. Tisk kódu stisknuté klávesy a modifikátoru(ů)
Po stisku klávesy se zavolá handler deklarovaný funkcí nazvanou on_key_down; naopak při puštění/uvolnění klávesy se zavolá handler on_key_up. Handleru on_key_down se předává kód klávesy, bitové pole s modifikátory a taktéž Unicode znak, který odpovídá stisknuté kombinaci (klávesa „A“ vrátí „a“ zatímco „Shift+A“ vrátí „A“). V další úpravě demonstračního příkladu zobrazíme po stisku jakékoli klávesy její kód, modifikátory (Shift atd.) a taktéž Unicode znak, který odpovídá stisknuté klávese (jen pokud to má význam – ne všechny klávesy reprezentují reálné znaky):
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (240, 240) def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def on_key_down(key, mod, unicode): print(key, mod, unicode)
6. Ukončení aplikace zvolenou klávesou
Nyní se pokusme náš prozatím velmi primitivní demonstrační příklad upravit, a to takovým způsobem, aby bylo možné aplikaci ukončit klávesou Esc. Prozatím je totiž nutné okno aplikace explicitně zavřít s využitím prostředků správce oken (popř. použít utilitu kill, xkill apod.). Demonstrační příklad je nutné nepatrně rozšířit, a to konkrétně o naprogramovanou reakci na událost typu „stisk klávesy“ představovanou handlerem on_key_down. Ve funkci s naprogramovanou reakcí na tuto událost pouze otestujeme, jaká klávesa byla stisknuta. A pokud se bude skutečně jednat o klávesu Esc, dojde k ukončení celé aplikace funkcí exit (což je ovšem odlišná funkce než sys.exit):
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (240, 240) def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def on_key_down(key, mod, unicode): if key == keys.ESCAPE: exit()
7. Posun spritu s využitím kurzorových šipek
Další modifikace našeho postupně upravovaného demonstračního příkladu bude spočívat v tom, že umožníme pohyb spritu na obrazovce s využitím kurzorových kláves. Využijeme zde tedy dvě vlastnosti nástroje Pygame Zero: možnost měnit pozici spritu na obrazovce změnou jeho souřadnic a reakci na stisk kláves, konkrétně kurzorových šipek. Pokusme se tedy o vytvoření první varianty příkladu:
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (240, 240) def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def on_key_down(key, mod, unicode): if key == keys.ESCAPE: exit() if key == keys.UP: sprite.top -= 1 if key == keys.DOWN: sprite.top += 1 if key == keys.LEFT: sprite.left -= 1 if key == keys.RIGHT: sprite.left += 1
Pokud se nyní po spuštění příkladu příkazem pgzrun pokusíte o stisk kurzorových kláves, uvidíte, že každý stisk klávesy odpovídá jedinému posunu spritu o pixel doleva, doprava, nahoru či dolů. Teprve po puštění/uvolnění klávesy a jejím opětovném stisku se sprint posune o další pixel. To pravděpodobně není očekávané chování, takže budeme muset náš příklad ještě upravit.
8. Posun spritu ve funkci update
Pro plynulý pohyb spritu můžeme použít ještě jeden přístup – samotný posun bude realizován ve funkci update, která je (pokud pochopitelně existuje) automaticky volaná pravidelně každou šedesátinu sekundy. Pokud tedy v této funkci posuneme sprite o jeden pixel (libovolným směrem), bude jeho rychlost rovna šedesáti pixelům za sekundu. Musíme si tedy zapamatovat směr pohybu spritu, například v dvojici globálních proměnných:
dx = 0 dy = 0
Tyto proměnné použijeme ve funkci update:
def update(): sprite.left += dx sprite.top += dy
A modifikovat je budeme při detekci stisku klávesy, konkrétně některé kurzorové šipky. V tomto kódu přímo nastavujeme hodnoty globálních proměnných, takže musíme provést jejich deklaraci v sekci global (jinak by se vytvořily lokální proměnné dx, resp. dy):
def on_key_down(key, mod, unicode): global dx, dy if key == keys.ESCAPE: exit() if key == keys.UP: dy = -1 if key == keys.DOWN: dy = 1 if key == keys.LEFT: dx = -1 if key == keys.RIGHT: dx = 1
directions = { keys.UP: (0, -1), keys.DOWN: (0, 1), keys.LEFT: (-1, 0), keys.RIGHT: (1, 0), } def on_key_down(key, mod, unicode): global dx, dy if key == keys.ESCAPE: exit() if key in directions: dx, dy = directions[key]
9. Úplný zdrojový kód upraveného příkladu
Upravený zdrojový kód demonstračního příkladu má délku pouze 33 programových řádků (včetně řádků prázdných):
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (240, 240) dx = 0 dy = 0 def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def update(): sprite.left += dx sprite.top += dy def on_key_down(key, mod, unicode): global dx, dy if key == keys.ESCAPE: exit() if key == keys.UP: dy = -1 if key == keys.DOWN: dy = 1 if key == keys.LEFT: dx = -1 if key == keys.RIGHT: dx = 1
10. Korektní reakce na stisk i puštění (uvolnění) klávesy
V případě, že předchozí variantu demonstračního příkladu spustíte, zjistíte, že je možné pomocí kurzorových šipek začít s plynulým přesunem spritu do libovolného z osmi základních směrů (nahoru, dolů, doleva, doprava a šikmo kombinací dvou na sebe kolmých směrů). Jediný problém spočívá v tom, že se posun spritu nezastaví, protože žádným způsobem – alespoň prozatím – nezjišťujeme, kdy jsou klávesy puštěny (uvolněny). Tento nedostatek můžeme snadno napravit, například tak, že pokud je puštěna alespoň jedna kurzorová klávesa, pohyb spritu se zastaví. Tento kód je nutné zapsat do handleru on_key_up:
def on_key_up(key, mod): global dx, dy if key == keys.ESCAPE: exit() if key in (keys.UP, keys.DOWN, keys.LEFT, keys.RIGHT): dx = 0 dy = 0
Alternativně je možné reagovat na každou kurzorovou šipku zvlášť, což umožňuje měnit směr ze šikmého na vodorovný nebo svislý (změna kombinace kláves):
def on_key_up(key, mod): global dx, dy if key == keys.ESCAPE: exit() if key == keys.UP or key == keys.DOWN: dy = 0 if key == keys.LEFT or key == keys.RIGHT: dx = 0
11. Úplný zdrojový kód upraveného příkladu
Ukažme si nyní úplný zdrojový kód našeho upraveného demonstračního příkladu. Stále se jedná o krátký kód o délce čtyřiceti dvou programových řádků, i když již provádí relativně složitou činnost:
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (240, 240) dx = 0 dy = 0 def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def update(): sprite.left += dx sprite.top += dy def on_key_down(key, mod, unicode): global dx, dy if key == keys.ESCAPE: exit() if key == keys.UP: dy = -1 if key == keys.DOWN: dy = 1 if key == keys.LEFT: dx = -1 if key == keys.RIGHT: dx = 1 def on_key_up(key, mod): global dx, dy if key == keys.ESCAPE: exit() if key in (keys.UP, keys.DOWN, keys.LEFT, keys.RIGHT): dx = 0 dy = 0
12. Posun spritu společně s kurzorem myši
Nyní již umíme dostatečným způsobem pracovat s klávesnicí, takže se podívejme na způsob práce s myší. K dispozici jsou tři typy handlerů, které jsou určeny pro reakci na pohyb myši popř. na stisk či uvolnění tlačítek myši:
- on_mouse_down: stisk tlačítka myši
- on_mouse_up: uvolnění tlačítka myši
- on_mouse_move: posun kurzoru myši (se stiskem nebo bez stisku tlačítka)
Další demonstrační příklad bude ve skutečnosti kratší, než příklady předchozí. Upravíme ho totiž takovým způsobem, že sprite bude sledovat kurzor myši (pokud bude kurzor umístěn v ploše okna aplikace). Použijeme tedy poslední handler nazvaný on_mouse_move. Tomuto handleru se předává trojice parametrů – pozice myši (absolutní v rámci okna), relativní změna kurzoru a bitové pole s kódy stlačených tlačítek myši). Nás nyní bude zajímat pouze hodnota prvního parametru, což je dvojice souřadnic (x,y):
def on_mouse_move(pos, rel, buttons): sprite.pos = pos
Úplný zdrojový kód příkladu se zkrátí i proto, že nebudeme potřebovat dvojici pomocných globálních proměnných (a zmenšení globálního stavu je vždy dobrá cesta):
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (240, 240) def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def on_key_down(key, mod, unicode): if key == keys.ESCAPE: exit() def on_mouse_move(pos, rel, buttons): sprite.pos = pos
13. Posun spritu po stisku libovolného tlačítka myši
Zdrojový kód demonstračního příkladu můžeme upravit také tak, že se sprite přesune na novou pozici kurzoru po stisku (libovolného) tlačítka myši. Úprava je v tomto případě triviální – pouze přejmenujeme handler on_mouse_move na on_mouse_down a odstraníme parametr obsahující relativní změnu pozice kurzoru. Nový kód bude vypadat následovně:
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (240, 240) def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def on_key_down(key, mod, unicode): if key == keys.ESCAPE: exit() def on_mouse_down(pos, button): sprite.pos = pos
Po spuštění příkladu můžeme kurzor myši přesunout na libovolné místo v okně aplikace a po stisku tlačítka se na toto místo přesune i sprite, a to takovým způsobem, že jeho střed bude ležet na levý horní roh šipky (což by měl být výchozí tvar kurzoru).
14. Základy tvorby animací v Pygame Zero
Pokud bychom v demonstračních příkladech namísto spritu ve tvaru zeměkoule požívali nějakého panáčka, byl by pohyb (nebo lépe řečeno přeskok na novou pozici) po stisku tlačítka myši neakceptovatelný. Lepší by bylo, aby se sprite/panáček na nové místo přesunul plynulým pohybem. K tomuto účelu je možné v knihovně Pygame Zero použít animace (alternativně je samozřejmě možné pohyb počítat explicitně vlastním programovým kódem). Animace jsou ve skutečnosti relativně jednoduše použitelné, neboť slouží k více či méně plynulé změně nějakých atributů zvoleného objektu – nemusí se tedy ve všech případech nutně jednat o animaci v grafickém slova smyslu. Samotná animace se vytvoří funkcí animate, které se předávají minimálně dva parametry:
- Objekt, jehož atributy se mají v rámci animace měnit
- Atribut(y) a jejich konečné parametry po dokončení animace
Podívejme se nyní na jednoduchý (umělý) příklad, v němž budeme postupně měnit horizontální pozici spritu, který plynule přejede přes celou obrazovku. Animovaným objektem tedy bude sprite, atributem pak x, koncovou hodnotou 480, což je šířka obrazovky:
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (0, 240) animation = animate(sprite, x=WIDTH) def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def on_key_down(key, mod, unicode): if key == keys.ESCAPE: exit()
Animaci lze i zpomalit na pět sekund (implicitně je provedena v jedné sekundě):
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (0, 240) animation = animate(sprite, x=WIDTH, duration=5) def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def on_key_down(key, mod, unicode): if key == keys.ESCAPE: exit()
15. Animovaný přesun spritu na pozici kurzoru myši
Příklad ze třinácté kapitoly lze velmi snadno upravit takovým způsobem, aby se sprite přesunul na novou pozici na obrazovce plynulým přímočarým pohybem. Povšimněte si, jak je používaní animací elegantní:
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) sprite = Actor("sprite1.png") sprite.pos = (240, 240) def draw(): screen.fill(BACKGROUND_COLOR) sprite.draw() def on_key_down(key, mod, unicode): if key == keys.ESCAPE: exit() def on_mouse_down(pos, button): animate(sprite, pos=pos)
16. Pojmenované barvy podporované nástrojem Pygame Zero
Nástroj Pygame Zero importuje jména barev přímo z knihovny Pygame, odkud je tyto údaje snadné získat. Jedná se o tyto barvy (seřazené podle jména):
Barva | Barva | Barva | Barva | Barva |
---|---|---|---|---|
aliceblue | antiquewhite | antiquewhite1 | antiquewhite2 | antiquewhite3 |
antiquewhite4 | aquamarine | aquamarine1 | aquamarine2 | aquamarine3 |
aquamarine4 | azure | azure1 | azure2 | azure3 |
azure4 | beige | bisque | bisque1 | bisque2 |
bisque3 | bisque4 | black | blanchedalmond | blue |
blue1 | blue2 | blue3 | blue4 | blueviolet |
brown | brown1 | brown2 | brown3 | brown4 |
burlywood | burlywood1 | burlywood2 | burlywood3 | burlywood4 |
cadetblue | cadetblue1 | cadetblue2 | cadetblue3 | cadetblue4 |
chartreuse | chartreuse1 | chartreuse2 | chartreuse3 | chartreuse4 |
chocolate | chocolate1 | chocolate2 | chocolate3 | chocolate4 |
coral | coral1 | coral2 | coral3 | coral4 |
cornflowerblue | cornsilk | cornsilk1 | cornsilk2 | cornsilk3 |
cornsilk4 | cyan | cyan1 | cyan2 | cyan3 |
cyan4 | darkblue | darkcyan | darkgoldenrod | darkgoldenrod1 |
darkgoldenrod2 | darkgoldenrod3 | darkgoldenrod4 | darkgray | darkgreen |
darkgrey | darkkhaki | darkmagenta | darkolivegreen | darkolivegreen1 |
darkolivegreen2 | darkolivegreen3 | darkolivegreen4 | darkorange | darkorange1 |
darkorange2 | darkorange3 | darkorange4 | darkorchid | darkorchid1 |
darkorchid2 | darkorchid3 | darkorchid4 | darkred | darksalmon |
darkseagreen | darkseagreen1 | darkseagreen2 | darkseagreen3 | darkseagreen4 |
darkslateblue | darkslategray | darkslategray1 | darkslategray2 | darkslategray3 |
darkslategray4 | darkslategrey | darkturquoise | darkviolet | deeppink |
deeppink1 | deeppink2 | deeppink3 | deeppink4 | deepskyblue |
deepskyblue1 | deepskyblue2 | deepskyblue3 | deepskyblue4 | dimgray |
dimgrey | dodgerblue | dodgerblue1 | dodgerblue2 | dodgerblue3 |
dodgerblue4 | firebrick | firebrick1 | firebrick2 | firebrick3 |
firebrick4 | floralwhite | forestgreen | gainsboro | ghostwhite |
gold | gold1 | gold2 | gold3 | gold4 |
goldenrod | goldenrod1 | goldenrod2 | goldenrod3 | goldenrod4 |
gray | gray0 | gray1 | gray10 | gray100 |
gray11 | gray12 | gray13 | gray14 | gray15 |
gray16 | gray17 | gray18 | gray19 | gray2 |
gray20 | gray21 | gray22 | gray23 | gray24 |
gray25 | gray26 | gray27 | gray28 | gray29 |
gray3 | gray30 | gray31 | gray32 | gray33 |
gray34 | gray35 | gray36 | gray37 | gray38 |
gray39 | gray4 | gray40 | gray41 | gray42 |
gray43 | gray44 | gray45 | gray46 | gray47 |
gray48 | gray49 | gray5 | gray50 | gray51 |
gray52 | gray53 | gray54 | gray55 | gray56 |
gray57 | gray58 | gray59 | gray6 | gray60 |
gray61 | gray62 | gray63 | gray64 | gray65 |
gray66 | gray67 | gray68 | gray69 | gray7 |
gray70 | gray71 | gray72 | gray73 | gray74 |
gray75 | gray76 | gray77 | gray78 | gray79 |
gray8 | gray80 | gray81 | gray82 | gray83 |
gray84 | gray85 | gray86 | gray87 | gray88 |
gray89 | gray9 | gray90 | gray91 | gray92 |
gray93 | gray94 | gray95 | gray96 | gray97 |
gray98 | gray99 | green | green1 | green2 |
green3 | green4 | greenyellow | grey | grey0 |
grey1 | grey10 | grey100 | grey11 | grey12 |
grey13 | grey14 | grey15 | grey16 | grey17 |
grey18 | grey19 | grey2 | grey20 | grey21 |
grey22 | grey23 | grey24 | grey25 | grey26 |
grey27 | grey28 | grey29 | grey3 | grey30 |
grey31 | grey32 | grey33 | grey34 | grey35 |
grey36 | grey37 | grey38 | grey39 | grey4 |
grey40 | grey41 | grey42 | grey43 | grey44 |
grey45 | grey46 | grey47 | grey48 | grey49 |
grey5 | grey50 | grey51 | grey52 | grey53 |
grey54 | grey55 | grey56 | grey57 | grey58 |
grey59 | grey6 | grey60 | grey61 | grey62 |
grey63 | grey64 | grey65 | grey66 | grey67 |
grey68 | grey69 | grey7 | grey70 | grey71 |
grey72 | grey73 | grey74 | grey75 | grey76 |
grey77 | grey78 | grey79 | grey8 | grey80 |
grey81 | grey82 | grey83 | grey84 | grey85 |
grey86 | grey87 | grey88 | grey89 | grey9 |
grey90 | grey91 | grey92 | grey93 | grey94 |
grey95 | grey96 | grey97 | grey98 | grey99 |
honeydew | honeydew1 | honeydew2 | honeydew3 | honeydew4 |
hotpink | hotpink1 | hotpink2 | hotpink3 | hotpink4 |
indianred | indianred1 | indianred2 | indianred3 | indianred4 |
ivory | ivory1 | ivory2 | ivory3 | ivory4 |
khaki | khaki1 | khaki2 | khaki3 | khaki4 |
lavender | lavenderblush | lavenderblush1 | lavenderblush2 | lavenderblush3 |
lavenderblush4 | lawngreen | lemonchiffon | lemonchiffon1 | lemonchiffon2 |
lemonchiffon3 | lemonchiffon4 | lightblue | lightblue1 | lightblue2 |
lightblue3 | lightblue4 | lightcoral | lightcyan | lightcyan1 |
lightcyan2 | lightcyan3 | lightcyan4 | lightgoldenrod | lightgoldenrod1 |
lightgoldenrod2 | lightgoldenrod3 | lightgoldenrod4 | lightgoldenrodyellow | lightgray |
lightgreen | lightgrey | lightpink | lightpink1 | lightpink2 |
lightpink3 | lightpink4 | lightsalmon | lightsalmon1 | lightsalmon2 |
lightsalmon3 | lightsalmon4 | lightseagreen | lightskyblue | lightskyblue1 |
lightskyblue2 | lightskyblue3 | lightskyblue4 | lightslateblue | lightslategray |
lightslategrey | lightsteelblue | lightsteelblue1 | lightsteelblue2 | lightsteelblue3 |
lightsteelblue4 | lightyellow | lightyellow1 | lightyellow2 | lightyellow3 |
lightyellow4 | limegreen | linen | magenta | magenta1 |
magenta2 | magenta3 | magenta4 | maroon | maroon1 |
maroon2 | maroon3 | maroon4 | mediumaquamarine | mediumblue |
mediumorchid | mediumorchid1 | mediumorchid2 | mediumorchid3 | mediumorchid4 |
mediumpurple | mediumpurple1 | mediumpurple2 | mediumpurple3 | mediumpurple4 |
mediumseagreen | mediumslateblue | mediumspringgreen | mediumturquoise | mediumvioletred |
midnightblue | mintcream | mistyrose | mistyrose1 | mistyrose2 |
mistyrose3 | mistyrose4 | moccasin | navajowhite | navajowhite1 |
navajowhite2 | navajowhite3 | navajowhite4 | navy | navyblue |
oldlace | olivedrab | olivedrab1 | olivedrab2 | olivedrab3 |
olivedrab4 | orange | orange1 | orange2 | orange3 |
orange4 | orangered | orangered1 | orangered2 | orangered3 |
orangered4 | orchid | orchid1 | orchid2 | orchid3 |
orchid4 | palegoldenrod | palegreen | palegreen1 | palegreen2 |
palegreen3 | palegreen4 | paleturquoise | paleturquoise1 | paleturquoise2 |
paleturquoise3 | paleturquoise4 | palevioletred | palevioletred1 | palevioletred2 |
palevioletred3 | palevioletred4 | papayawhip | peachpuff | peachpuff1 |
peachpuff2 | peachpuff3 | peachpuff4 | peru | pink |
pink1 | pink2 | pink3 | pink4 | plum |
plum1 | plum2 | plum3 | plum4 | powderblue |
purple | purple1 | purple2 | purple3 | purple4 |
red | red1 | red2 | red3 | red4 |
rosybrown | rosybrown1 | rosybrown2 | rosybrown3 | rosybrown4 |
royalblue | royalblue1 | royalblue2 | royalblue3 | royalblue4 |
saddlebrown | salmon | salmon1 | salmon2 | salmon3 |
salmon4 | sandybrown | seagreen | seagreen1 | seagreen2 |
seagreen3 | seagreen4 | seashell | seashell1 | seashell2 |
seashell3 | seashell4 | sienna | sienna1 | sienna2 |
sienna3 | sienna4 | skyblue | skyblue1 | skyblue2 |
skyblue3 | skyblue4 | slateblue | slateblue1 | slateblue2 |
slateblue3 | slateblue4 | slategray | slategray1 | slategray2 |
slategray3 | slategray4 | slategrey | snow | snow1 |
snow2 | snow3 | snow4 | springgreen | springgreen1 |
springgreen2 | springgreen3 | springgreen4 | steelblue | steelblue1 |
steelblue2 | steelblue3 | steelblue4 | tan | tan1 |
tan2 | tan3 | tan4 | thistle | thistle1 |
thistle2 | thistle3 | thistle4 | tomato | tomato1 |
tomato2 | tomato3 | tomato4 | turquoise | turquoise1 |
turquoise2 | turquoise3 | turquoise4 | violet | violetred |
violetred1 | violetred2 | violetred3 | violetred4 | wheat |
wheat1 | wheat2 | wheat3 | wheat4 | white |
whitesmoke | yellow | yellow1 | yellow2 | yellow3 |
yellow4 | yellowgreen |
from pygame.colordict import THECOLORS for i, color in enumerate(sorted(THECOLORS)): if i % 5 == 0: print("<tr>", end="") print("<td>" + color + "</td>", end="") if i % 5 == 4: print("</tr>")
17. Zobrazení pojmenovaných barev podporovaných nástrojem Pygame Zero
V této kapitole si ukážeme zdrojový kód pomocného příkladu, po jehož spuštění se zobrazí vybrané pojmenované barvy, které jsou podporovány nástrojem Pygame Zero. Příklad je ve skutečnosti poměrně jednoduchý, protože pouze vykreslí vyplněný obdélník danou barvou a následně do plochy tohoto obdélníka zapíše číslo barvy. Vzhledem k tomu, že barva obdélníka může být jakákoli (a text by tedy nemusel být čitelný), využijeme možnost zobrazit text s obarveným okrajem. A pokud bude text například bílý a okraj černý, bude takový text (nebo alespoň jeho okraj) viditelný na jakémkoli pozadí.
Obrázek 4: Některé pojmenované barvy v Pygame Zero.
Jména podporovaných barev naleznete v tabulce získané následujícím způsobem (používáme v něm přímo knihovnu Pygame):
from pygame.colordict import THECOLORS for i, color in enumerate(sorted(THECOLORS)): print(i, color)
Zdrojový kód demonstračního příkladu, který tyto barvy (resp. jejich vybranou podskupinu) vykreslí, může vypadat takto:
from pygame.colordict import THECOLORS import random WIDTH = 480 HEIGHT = 480 colors = THECOLORS def draw(): screen.fill("gray") for j in range(3): x = 10 + j * 160 for j in range(12): y = 12 + j * 40 color_name, color_value = random.choice(list(colors.items())) rect = Rect((x, y-8), (140, 30)) screen.draw.filled_rect(rect, color_value) screen.draw.text(color_name, (x, y), owidth=1, fontsize=24, ocolor="white", color="black")
18. Relevantní funkce z knihovny Pygame
V této kapitole jsou uvedeny odkazy na dokumentaci k funkcím knihovny Pygame, které jsou interně používány i projektem Pygame Zero. Tyto funkce jsou vidět v některých chybových hlášeních, protože i přes snahy autorů Pygame Zero není odstínění od knihovny Pygame úplné (což je možná jeden z největších současných nedostatků tohoto projektu):
- pygame.init()
http://www.pygame.org/docs/ref/pygame.html#pygame.init - pygame.quit()
http://www.pygame.org/docs/ref/pygame.html#pygame.quit - pygame.display.set_mode()
http://www.pygame.org/docs/ref/display.html#pygame.display.set_mode - pygame.display.set_caption()
http://www.pygame.org/docs/ref/display.html#pygame.display.set_caption - pygame.display.update()
http://www.pygame.org/docs/ref/display.html#pygame.display.update - pygame.event.get()
http://www.pygame.org/docs/ref/event.html#pygame.event.get - pygame.time.wait()
http://www.pygame.org/docs/ref/time.html#pygame.time.wait - pygame.time.Clock.tick()
http://www.pygame.org/docs/ref/time.html#pygame.time.Clock.tick - pygame.draw.line()
http://www.pygame.org/docs/ref/draw.html#pygame.draw.line - pygame.draw.circle()
http://www.pygame.org/docs/ref/draw.html#pygame.draw.circle - pygame.draw.rect()
http://www.pygame.org/docs/ref/draw.html#pygame.draw.rect - pygame.draw.ellipse()
http://www.pygame.org/docs/ref/draw.html#pygame.draw.ellipse - pygame.key.get_pressed
https://www.pygame.org/docs/ref/key.html#pygame.key.get_pressed - pygame.key.get_mods
https://www.pygame.org/docs/ref/key.html#pygame.key.get_mods - pygame.mouse.get_pos
https://www.pygame.org/docs/ref/mouse.html#pygame.mouse.get_pos - pygame.mouse.get_rel
https://www.pygame.org/docs/ref/mouse.html#pygame.mouse.get_rel - pygame.mouse.get_pressed
https://www.pygame.org/docs/ref/mouse.html#pygame.mouse.get_pressed
19. Repositář s demonstračními příklady
Zdrojové kódy všech popsaných demonstračních příkladů určených pro Python 3 a nástroj Pygame Zero byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/most-popular-python-libs. V případě, že nebudete chtít klonovat celý repositář (ten je ovšem stále velmi malý, dnes má velikost zhruba několik desítek kilobajtů), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující dvojici tabulek:
Obrázky použité v demonstračních příkladech jsou uloženy na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/pygame_zero/images.
20. Odkazy na Internetu
- Welcome to Pygame Zero
https://pygame-zero.readthedocs.io/en/stable/index.html - Other libraries like Pygame Zero
https://pygame-zero.readthedocs.io/en/stable/other-libs.html - Principles of Pygame Zero
https://pygame-zero.readthedocs.io/en/stable/principles.html - Built-in Objects (in Pygame Zero)
https://pygame-zero.readthedocs.io/en/stable/builtins.html - Pygame
https://www.pygame.org/news - Kniha: Coding Games With Pygame Zero & Python: Student workbook
https://bookerystore.com/downloads/coding-games-with-pygame-zero-python-student-workbook/ - Projekty založené na Pygame
https://www.pygame.org/tags/all - Domovská stránka projektu LÖVE
https://love2d.org/ - PyWeek, a bi-annual game jam to write games in Python
https://pyweek.org/ - Teaching a kid to code with Pygame Zero
https://www.mattlayman.com/blog/2019/teach-kid-code-pygame-zero/ - Games with PyGame Zero
https://codewith.mu/en/tutorials/1.0/pgzero - Coding Games With Pygame Zero & Python: Student workbook (2nd edition)
https://electronstudio.github.io/pygame-zero-book/ - Historie vývoje počítačových her (116. část – vývoj her v současnosti: od assembleru k PyGame)
https://www.root.cz/clanky/historie-vyvoje-pocitacovych-her-116-cast-vyvoj-her-v-soucasnosti-od-assembleru-k-pygame/ - Lua + LÖVE: vytvořte si vlastní hru
https://www.root.cz/clanky/lua-love-vytvorte-si-vlastni-hru/ - Hrátky se systémem LÖVE
https://www.root.cz/clanky/hratky-se-systemem-love/ - Vytváříme hru v systému LÖVE
https://www.root.cz/clanky/vytvarime-hru-v-systemu-love/ - Hrátky se systémem LÖVE – částicové systémy
https://www.root.cz/clanky/hratky-se-systemem-love-casticove-systemy/ - Hrátky se systémem LÖVE – kolize a odrazy těles
https://www.root.cz/clanky/hratky-se-systemem-love-ndash-kolize-a-odrazy-teles/ - Hrátky se systémem LÖVE – kolize a odrazy těles II
https://www.root.cz/clanky/hratky-se-systemem-love-kolize-a-odrazy-teles-ii/ - Hrátky se systémem LÖVE – pružné vazby mezi tělesy
https://www.root.cz/clanky/hratky-se-systemem-love-pruzne-vazby-mezi-telesy/ - Hrátky se systémem LÖVE – dokončení
https://www.root.cz/clanky/hratky-se-systemem-love-dokonceni/ - Seriál Letní škola programovacího jazyka Logo
http://www.root.cz/serialy/letni-skola-programovaciho-jazyka-logo/ - Scratch: oficiální stránka projektu
http://scratch.mit.edu/ - Scratch: galerie projektů vytvořených ve Scratchi
http://scratch.mit.edu/galleries/browse/newest - Scratch: nápověda
file:///usr/share/scratch/Help/en/index.html - Scratch: obrazovky nápovědy
file:///usr/share/scratch/Help/en/allscreens.html - Scratch (Wikipedie CZ)
http://cs.wikipedia.org/wiki/Scratch - Scratch (programming language)
http://en.wikipedia.org/wiki/Scratch_(programming_language) - Scratch Modification
http://wiki.scratch.mit.edu/wiki/Scratch_Modification - Scratch Lowers Resistance to Programming
http://www.wired.com/gadgetlab/2009/03/scratch-lowers/ - Snap!
http://snap.berkeley.edu/ - Prostředí Snap!
http://snap.berkeley.edu/snapsource/snap.html - Alternatives to Scratch
http://wiki.scratch.mit.edu/wiki/Alternatives_to_Scratch - Snap! (programming language)
https://en.wikipedia.org/wiki/Snap!_(programming_language) - Kniha o Basicu-256
http://www.basicbook.org/files/syw2l2p_b256.pdf/ - Basic-256 home page
http://www.basic256.org/index_en - Basic-256 Language Documentation
http://doc.basic256.org/doku.php - Basic-256 Art Gallery
http://www.basic256.org/artgallery - Basic-256 Tutorial
http://www.basic256.org/tutorials - Why BASIC?
http://www.basic256.org/whybasic - A book to teach ANYBODY how to program a computer (using BASIC)
http://www.basicbook.org/ - Sprite ve Scratchi
https://en.scratch-wiki.info/wiki/Sprite - Scratch Modification
https://en.scratch-wiki.info/wiki/Scratch_Modification - 3D Programming in Python – Part 1
https://greendalecs.wordpress.com/2012/04/21/3d-programming-in-python-part-1/ - A very basic Pyglet tutorial
http://www.natan.termitnjak.net/tutorials/pyglet_basic.html - Alpha blending
https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending - Pygame Colors
https://pygame-zero.readthedocs.io/en/latest/colors_ref.html - Python Color Constants Module
https://www.webucator.com/blog/2015/03/python-color-constants-module/