Obsah
1. Programovací jazyky a knihovny určené pro výuku základů počítačové grafiky a interaktivních her
3. Skládání složitějších programů s využitím jednotlivých bloků
4. Přednosti, zápory a omezení Scratche
7. Základní strukturované příkazy z Basicu-256
8. Grafický výstup v Basicu-256
9. Frameworky a knihovny navržené pro snadnou a rychlou tvorbu 2D her
15. Vytvoření a spuštění prázdného projektu
16. Vyplnění pozadí určenou barvou
17. Vykreslení spritů do 2D scény
18. Vykreslení rastrového obrázku na pozadí
19. Repositář s demonstračními příklady
1. Programovací jazyky a knihovny určené pro výuku základů počítačové grafiky a interaktivních her
It's a bit like learning natural languages: the earlier the better.
Michael Kölling
V současnosti existuje a navíc je i aktivně používáno několik desítek různých programovacích jazyků, ať již jazyků interpretovaných či překládaných do nativního (strojového) kódu nebo bajtkódu. Až na několik výjimek se však jedná o takové jazyky, které nejsou příliš vhodné pro první seznámení dětí s návrhem algoritmů a jednoduchých aplikací. Z tohoto důvodu vzniklo a stále ještě vzniká poměrně velké množství projektů, jejichž cílem je seznámit děti předškolního věku či děti na prvním stupni ZŠ se základem algoritmizace a mnohdy i s tvorbou počítačové grafiky (protože grafický výstup či dokonce animace nebo interaktivní hry jsou nepochybně atraktivní, zejména v porovnání s „fádním“ textovým výstupem). Jmenujme například projekty Logo, Scratch, BYOB, Snap!, Alice, Android App Inventor, Starlogo, Etoys, DesignBlocks, Pocket Code, Hopscotch, Blockly, Greenfoot, Processing, GameMaker nebo poněkud kontroverzní Microsoft Small Basic.
Obrázek 1: Moderní integrovaná vývojová prostředí (v případě, že Eclipse stále řadíme mezi moderní IDE :-) jsou sice pro amatérské i profesionální programátory velmi užitečná, ovšem při výuce může jejich velká variabilita být v některých ohledech spíše kontraproduktivní a bylo by výhodnější používat prostředí s menším množstvím voleb.
Oblíbeným jazykem v této oblasti bývalo Logo (a mnohé jeho dialekty), které jsem dříve taktéž prosazoval. Ovšem ukazuje se, že i na prvním stupni základní školy je dosti složité vysvětlit pojem úhlu, který je v Logu celkem zásadní (v programech se totiž ovládá želvička pohybující se po ploše obrazovky). Naproti tomu nemají děti prakticky žádný problém s pochopením principu bitmapové grafiky a pixelů; možná se ani není čemu divit, neboť tato generace již vyrůstá na Minecraftu :-). I z tohoto důvodu budou v dnešním článku zmíněny dva dosti odlišné projekty: Scratch se zaměřením na vizuální tvorbu programů, který používá želví grafiku známou z Loga a projekt nazvaný Basic-256, v němž lze několika málo příkazy vykreslit i poměrně složité rastrové obrázky. Kromě Scratche se zmíníme i o příbuzném projektu Snap!.
Obrázek 2: Comenius Logo, které se používalo i v našem školství.
V článku si ve stručnosti představíme možnou trojici nástrojů, která by mohla být vhodná pro výuku programování:
- Nástroj založený na vizuálním skládání bloků. Jedná se o projekty Scratch (jak desktopová, tak i webová varianta), Snap!, popř. o projekty typu MakeCode (použitý například pro programování jednodeskového mikropočítače micro:bit.
- Jednoduché operace s rastrovými obrazy, a to již s využitím „reálného“ programového kódu. Pro tento účel se pochopitelně dají použít plnohodnotné obecné programovací jazyky s vhodnou knihovnou, ovšem lze využít i spíše minimalisticky pojatý projekt typu Basic-256.
- Nástroj umožňující tvorbu interaktivní grafiky, her, animací atd. V této oblasti máme k dispozici minimálně dva projekty, a to LÖVE (založeno na jazyku Lua) a Pygame Zero (založeno na Pythonu). My se dnes zaměříme především na druhý zmíněný projekt, pro který vyšly i knihy určené právě pro děti, které se zajímají o programování. A z hlediska větší popularity Pythonu je možná výhodnější začít právě s Pygame Zero.
2. Systém Scratch
Scratch uses hands-on, active learning; it is visually appealing; it allows users to express their own creativity and to build on their own experiences; it gives immediate, understandable feedback; and it allows users to avoid syntax errors without focusing on minutiae, freeing them to focus on processes and concepts.
NCWIT study
Některé v praxi používané programovací jazyky (například Python či spíše Lua – více viz druhá část článku) je sice možné použít pro výuku programování, ovšem pro děti předškolního věku nebo pro děti na prvním stupni základních škol se podle mého názoru příliš nehodí, a to hned z několika důvodů. Jedním z těchto důvodů je nutnost zápisu algoritmů pomocí více či méně strukturovaného textu, jehož syntaxe je hlídána buď interpretrem či překladačem. Jedná se o nejdéle používaný způsob programování, jehož počátky můžeme hledat v hluboké počítačové minulosti, protože první překladač pracující se strojovým textem byl vytvořen již v rozmezí let 1951 až 1952 Grace Hopperovou v rámci projektu A-0 (Arithmetic Language version 0), který byl později následován známým FORTRANem navrženým Johnem W. Backusem a jeho vývojovým týmem. Ovšem v průběhu oněch cca šedesáti let se znovu a znovu objevovaly více či méně úspěšné pokusy o vizuální návrh algoritmů, tj. o tvorbu programů nikoli zápisem strukturovaného zdrojového textu, ale návrhem algoritmů pomocí diagramů vytvářených například s využitím myši, gesty či v minulosti pomocí světelného pera.
Obrázek 3: Bloky, z nichž se programy tvořené ve Scratchi skládají, jsou na základě své funkce rozděleny do několika kategorií. Povšimněte si, že prostředí Scratche bylo téměř kompletně počeštěno; jedna z mála částí ponechaná v angličtině je nápověda k jednotlivým příkazům (i když i tato část se pravděpodobně brzy přeloží).
Poměrně dobře známé jsou například pokusy o přímý „překlad“ klasických vývojových diagramů, využití takzvaných kopenogramů atd. V současnosti někteří analytici a vývojáři využívají vizuální/grafický jazyk UML (což je ovšem jen pomůcka) či BPM (návrh business procesů, ovšem s vhodně zvolenými bloky se vlastně jedná o plnohodnotný jazyk). V oblasti software určeného pro výuku programování se využívá podobný princip, jako v případě vývojových diagramů – možnost zápisu (či možná lépe řečeno deklarace) algoritmů s využitím bloků představujících jednotlivé příkazy či volané funkce, které jsou doplněny o základní strukturované příkazy určené pro tvorbu rozhodovacích podmínek a programových smyček. Na tomto principu, tj. na vylepšených a vizuálně přitažlivějších vývojových diagramech, je postaven i projekt Scratch, v němž jsou uživatelům nabídnuty základní stavební bloky, z nichž se program skládá, přičemž je ponecháno pouze na uživateli, jakým způsobem tyto bloky využije ve svých programech.
Obrázek 4: Programy se ve Scratchi tvoří přetahováním příkazových bloků z oblasti umístěné v levé části okna do střední oblasti, zde nadepsané „Skripty“ (nová verze Scratche používá nepatrně odlišný design grafického uživatelského rozhraní). Tento screenshot byl získán z „klasického“ desktopového prostředí Scratche. Dnes je již k dispozici i webová verze dostupná na https://scratch.mit.edu/projects/editor/, která nevyžaduje žádnou instalaci.
Díky způsobu implementace skládání bloků pod sebe, popř. do sebe (s využitím „zámků“, podobně jako u puzzle) je zajištěno, že program bude po syntaktické stránce vždy v pořádku, což je důležité, protože odpadá pro děti nudná oprava překlepů, hledání chybějících středníků, hlídání párovosti závorek i další činnosti spojené s prací s běžnými programovacími jazyky. Uživatel se tedy musí starat o to podstatné – o sémantiku navrhované aplikace.
Obrázek 5: Editor bitmapových spritů zabudovaný přímo ve Scratchi.
3. Skládání složitějších programů s využitím jednotlivých bloků
Tvorba programů ve Scratchi je jednoduchá a po krátkém zaučení i intuitivní – v levé části okna (Scratch verze 1) se postupně vybírají příkazové bloky, které se přetahují do prostřední části okna, kde se z těchto bloků může skládáním tvořit program či programy. Běžný příkazový blok je vizuálně představován obdélníkem s několika výčnělky připomínajícími puzzle. Programové smyčky a podmínky jsou vyobrazeny jako složitější tvary umožňující vkládání dalších bloků dovnitř svého těla. S využitím těchto výčnělků se bloky spojují dohromady tak, aby tvořily sekvenci či dokonce strukturovaný program. V případě, že je zapotřebí sekvenci příkazů změnit, je možné bloky od sebe rozdělit, popř. vybraný blok smazat (přes menu zobrazené po stisku pravého tlačítka myši), zkopírovat (opět přes pravé tlačítko myši) či přesunout. Společně spojené bloky tvoří program, který je možné spustit doubleclickem. Na ploše Skripty je možné vytvořit i více programů, každý je tvořený množinou spojených bloků. Činnost každého bloku lze nezávisle na vlastním programu taktéž jednoduše ověřit – opět doubleclickem.
Obrázek 6: Velmi jednoduchá simulace Brownova pohybu naprogramovaná ve Scratchi.
Vizuální tvorba programů s využitím skládání příkazových bloků tvoří pouze jednu část snadnosti použití Scratche při výuce programování. Druhou částí je takzvaná pracovní (kreslicí) plocha s volitelným pozadím, po níž se mohou v závislosti na volaných příkazech pohybovat takzvané sprity, které navíc mohou při svém pohybu za sebou kreslit křivku (tj. stopu pohybu). Pod pojmem sprite je ve Scratchi myšlen rastrový obrázek, který může představovat například postavu či jiný pohyblivý nebo i statický předmět ve hře, zatímco pozadí umístěné na pracovní plochu (taktéž se jedná o rastrový obrázek) je většinou neměnné a může představovat pozadí hry, místnost, ve které se odehrává nějaký dialog atd. Scratch díky možnosti prakticky neomezeného pohybu spritů po pracovní ploše s volitelným kreslením cesty (stopy pohybu), kterou sprity vykonaly, umně integruje jak možnosti programovacích jazyků typu Karel či Baltazar (sprity umístěné a pohybující se po pomyslné šachovnici) a taktéž výše zmíněného programovacího jazyka Logo s neodmyslitelnou želvou, která se může pohybovat libovolným směrem po ploše.
Obrázek 7: Program pro vykreslení spirály, v němž se používá proměnná i programová smyčka.
Obrázek 8: Spirála vykreslená předchozím programem (s použitím jiného spritu, než obligátní želvičky).
4. Přednosti, zápory a omezení Scratche
Projekt Scratch se po relativně krátké době po svém představení veřejnosti stal velmi populární a to nejenom mezi učiteli základních škol (v USA a dalších zemích), ale i na středních školách a na školách vysokých (především na fakultách netechnického zaměření, to je ovšem již téma přesahující zaměření tohoto článku). Důvodů, které vedly k této popularitě bylo a je několik, největším však zůstává možnost vytvoření i poměrně složitého programu bez toho, aby byl uživatel nucen zdlouhavě studovat syntaxi a sémantiku jazyka, učit se ovládat vývojové prostředí nebo prostředí interpretru a navíc ještě reagovat na různá mnohdy kryptická chybová hlášení (ze syntaxe většiny běžných programovacích jazyků vyplývá, že například chybějící uzavírací závorka nebo klíčové slovo ukončující nějaký blok, vede ke vzniku chybového hlášení na jiném místě v programu, než kde se skutečně chyba nachází, což může být zejména pro začátečníky velmi frustrující).
Obrázek 9: Program sloužící pro vykreslení květu složeného z kružnic.
Další předností Scratche je jeho orientace na tvorbu multimediálních programů a taktéž možnost snadno prezentovat výsledný projekt na internetu, což děti může motivovat k tvorbě i poměrně komplikovaných aplikací (v minulosti byla tato možnost vykoupena nutností používat Flash, což mohlo v některých případech sdílení projektů komplikovat, nicméně v současnosti je již dokončen převod Scratche do plnohodnotného webového prostředí). Nesmíme zapomenout ani na to, že další přednosti Scratche by se mohly objevit při jeho použití v učebnách vybavených interaktivními tabulemi – jedná se vlastně o ideální aplikaci, která by mohla možnosti těchto tabulí plně využít.
Obrázek 10: Výsledek běhu programu z obrázku číslo 9.
Musíme se však zmínit i o některých problémech, kterými projekt Scratch trpí. Mnohé problémy či možná lépe řečeno omezení částečně vyplývají z toho, že jeho tvůrci nechtěli zbytečně komplikovat uživatelské rozhraní Scratche ani počet dostupných funkcí. Z těchto snah o minimalismus vyplývá mj. i například neexistence funkcí umožňujících práci se soubory, funkcí pro komunikaci přes počítačovou síť atd. Tento nedostatek je možné řešit nainstalováním různých modifikací (modů) Scratche, které však nejsou oficiálně podporovány. Ovšem mnohem závažnější je nemožnost tvorby vlastních stavebních bloků, které by nahrazovaly podprogramy/procedury/funkce. Právě z tohoto důvodu vzniklo několik rozšíření Scratche, především projekt BYOB – Build Your Own Block, který byl nahrazen novějším projektem nazvaným Snap! (http://snap.berkeley.edu/).
Obrázek 11: Výsledek běhu programu, v němž jsou použity proměnné a řídicí bloky.
5. Projekt Snap!
Jak již bylo naznačeno v předchozí kapitole, je Snap! dalším nástrojem, který je možné v případě potřeby využít pro výuku základních konceptů používaných při programování. Zjednodušeně řečeno je možné říci, že Snap! je obdobou Stratche a projektu BYOB (Build Your Own Block) přeneseného do prostředí Webu (HTML5+CSS+JavaScript), čímž odpadá nutnost instalace celého relativně velkého běhového prostředí původního Scratche a navíc se díky tomu, že Snap! běží přímo ve webovém prohlížeči, může tento projekt používat na širokém spektru různých zařízení, včetně tabletů a smartphonů (zde bude limitujícím faktorem velikost displeje). Navíc díky této vlastnosti projektu Snap! odpadají problémy s jeho nasazením do výuky (administrátoři se nemusí starat o instalaci ani o udržování projektu – což ostatně platí i pro Scratch 3.0). Prakticky všechny důležité vlastnosti Scratche zůstaly zachovány a navíc mají uživatelé možnost tvorby vlastních bloků a tím pádem i jednoduchého rozšiřování možností programovacího „jazyka“ (viz též screenshot číslo 14).
Obrázek 12: Prostředí programu Snap!
Obrázek 13: Editor spritů (stále se jedná o webovou aplikaci).
Obrázek 14: Vytvoření nového bloku uživatelem.
6. Basic-256
Dostáváme se k poněkud kontroverznímu tématu – k použití programovacího jazyka BASIC pro výuku programování, resp. pro tvorbu jednoduché počítačové grafiky. Pod pojmem „BASIC“ se může skrývat široké množství programovacích jazyků, které mnohdy nemají s původním prakticky nestrukturovaným BASICem známým z dob osmibitových mikropočítačů prakticky nic společného. Mnohdy právě naopak: některé moderní jazyky, v jejichž názvu se vyskytuje slovo „BASIC“ jsou plně strukturované, některé podporují objektově orientované programování (založené buď na třídách či na posílání zpráv objektům), mnohé BASICy nabízí uživatelům i pokročilé datové typy, jako jsou asociativní pole atd. A právě takovým poměrně moderním dialektem BASICu je Basic-256 zmíněný v tomto článku. Důvod, proč je zde tato aplikace zmíněna je jednoduchý – v Basic-256 se velmi snadno pracuje s grafikou, což je samozřejmě pro potřeby výuky ideální (je například velmi snadné vytvořit si programovou pomůcku pro výuku matematiky či geometrie).
Obrázek 15: Informace o projektu Basic-256.
Jak již bylo napsáno v předchozím odstavci, Basic-256 se od klasické školy BASICu v mnoha ohledech odklání, což je ostatně jen dobře. Jedná se o interpret doplněný o jednoduché vývojové prostředí s grafickým uživatelským rozhraním, který byl navržen s ohledem na to, aby se tento dialekt mohl použít při výuce programování, především na středních školách (podle mého názoru se však hodí spíše na základní školy). Tomu odpovídá jak jednoduchost a přehlednost vlastního vývojového prostředí, tak i sémantika jazyka, která samozřejmě podporuje strukturované programování. Na Internetu je dostupná cca 300stránková učebnice programování, v níž jsou použity příklady naprogramované právě v Basicu-256. Nejedná se však v žádném případě o učebnici, která by pouze popisovala syntaxi tohoto jazyka, právě naopak – ukázána je například práce se základními datovými strukturami (seznamy, zásobníkem, frontou) spolu s vysvětlením, jak jsou tyto datové struktury a operace nad nimi interně implementovány. Kromě toho lze v této učebnici najít i mnohé základní algoritmy, například řazení prvků v posloupnosti.
Obrázek 16: Uživatelské rozhraní je velmi jednoduše ovladatelné.
Obrázek 17: Do bitmapy je možné vykreslit mřížku, což je velmi užitečné, neboť se tak zvýrazní souřadnicový systém.
7. Základní strukturované příkazy z Basicu-256
V Basicu-256 jsou k dispozici prakticky všechny základní příkazy určené pro tvorbu strukturovaných programů složených z funkcí, subrutin (podprogramů), programových smyček a rozvětvení. Nalezneme zde i typicky BASICovou smyčku typu For-Next, která je podle mého názoru čitelnější, než podobně koncipovaná smyčka používaná v jazycích C, C++, Java či JavaScript. Podívejme se jen ve stručnosti na základní příklady:
i = 1 while i<1000 print i i=i*2 end while 1 2 4 8 16 32 64 128 256 512
for i=10 to 0 step -2 print i next i 10 8 6 4 2 0
x=10 do print x x=x/2 until x<0.1 10 5 2.5 1.25 0.625 0.3125 0.15625
for i=0 to 20 print i; if i % 2 =0 then print " sude" else print " liche" endif next i Zaciname 0 sude 1 liche 2 sude 3 liche 4 sude 5 liche 6 sude 7 liche 8 sude 9 liche 10 sude 11 liche 12 sude 13 liche 14 sude 15 liche 16 sude 17 liche 18 sude 19 liche 20 sude
Obrázek 18: Práce s rastrovou grafikou je v Basicu-256 skutečně snadná.
Kromě strukturovaných řídicích konstrukcí lze v Basicu-256 používat i (nechvalně) známé absolutní skoky, tj. příkazy typu GOTO a GOSUB), ovšem čísla řádků jsou nahrazena mnohem čitelnějšími textovými návěštími (label). Čísla řádků jsou považována za speciální typ návěští a jejich použití je doporučováno pouze při převodu starších programů do Basicu-256.
x: print "Old school style" goto x Old school style Old school style Old school style ... ... ...
Obrázek 19: Zobrazení průběhu funkce.
8. Grafický výstup v Basicu-256
Vývojové prostředí Basicu-256 obsahuje kromě velmi jednoduchého textového editoru i možnost zobrazení okna s hodnotami proměnných a taktéž grafickou oblast, do níž je možné provádět vykreslování. Ostatně právě možnost práce s grafikou, i když jsou k dispozici pouze základní vykreslovací příkazy, je pro jazyk určený pro výuku programování nedocenitelná. Zajímavé je, že grafickou plochu je možné zvětšit a dokonce lze vykreslit i mřížku a zvýraznit tak obrázek složený z (větších) pixelů. Taktéž je podporována práce se sprity, což relativně snadným a pochopitelným způsobem studentům přibližuje techniku používanou v 2D hrách. Ostatně podívejme se na trojici demonstračních příkladů, v nichž jsou použity základní grafické příkazy pro vymazání obrazovky, vykreslení bodu a taktéž pro vykreslení úsečky:
Obrázek 20: Lissajousovy obrazce.
Obrázek 21: Pokud je vykreslování pomalé, je možné zakázat automatické obnovování bitmapy po každém příkazu; o obnovení se postará explicitně zavolaný příkaz refresh.
9. Frameworky a knihovny navržené pro snadnou a rychlou tvorbu 2D her
Zdá se, že takřka ideálním tématem projektů, které je možné řešit již na druhém stupni ZŠ, jsou různé typy počítačových her. Ostatně stačí se jen podívat na projekty, které děti vytváří pro Micecraft a je zřejmé, že pro skutečně zajímavý projekt se minimálně část žáků nadchne. Pro tvorbu koncepčně většinou jednodušších 2D her lze použít různé typy skriptovacích vysokoúrovňových jazyků, které se začaly prosazovat již v dobách osmibitových mikropočítačů a své větší využití pak skriptovací jazyky nalezly na mnohem výkonnějších osobních počítačích. Kromě samotného jazyka je však nutné používat i nějakou vhodnou knihovnu pro práci s grafikou, zvukem a obsluhu vstupních zařízení (myš, klávesnice). V některých případech se jedná o jedinou knihovnu, která nabývá komplexnější podoby – frameworku. Pro potřeby výuky je důležité, aby byl takový framework postaven na snadno pochopitelných konceptech, které si lze snadno osvojit a vytvořit si tak mentální model celého frameworku. První dva dnes popisované frameworky – LÖVE a Pygame tento požadavek do jisté míry splňují; nejvíc se však „ideálu“ pravděpodobně přibližuje právě nástroj Pygame Zero.
Obrázek 22: Hra Gusanos, která využívá programovací jazyk Lua.
Před volbou frameworku použitého při výuce je nutné si zvolit vhodný (v tomto případě zcela jistě vysokoúrovňový) programovací jazyk. Určitý přelom (pravděpodobně není možné to nazvat přímo revolucí) v použití skriptovacích jazyků pro tvorbu her a jiných grafických aplikací nastal v roce 1993, kdy byla vydána první verze programovacího jazyka Lua. Tento programovací jazyk byl již od svých prvních verzí určen pro snadné vkládání (embedding) do jiných aplikací, mj. i her. A právě v oblasti počítačových her se Lua využívala a stále využívá velmi často, což ovšem není překvapivé, protože existuje relativně jednoduchá vazba mezi Luou a céčkem, samotný jazyk je vysokoúrovňový (dovolím si tvrdit, že skoro dosahuje kvalit Pythonu :-) a přitom pro spouštění skriptů je zapotřebí jen minimalisticky pojatý virtuální stroj. Tento jazyk byl použit v komerčních hrách, například v titulech Baldur's Gate, Grim Fandango, adventure hra Escape from Monkey Island či herní série Blitzkrieg, ovšem Lua se často objevuje i v nekomerčních titulech (příkladem open source hry využívající možností skriptovacích jazyků je klon Liera, který nese název Gusanos).
Obrázek 23: Další snímek ze hry Gusanos, která využívá programovací jazyk Lua.
10. LÖVE
Systém LÖVE, jehož starší (dopředně nekompatibilní!) varianta byla popsána v rámci seriálu o programovacím jazyku Lua, je určen pro jednoduchou a především rychlou tvorbu her s 2D grafikou, hudbou a zvuky, které jsou naskriptované ve výše zmíněném programovacím jazyku Lua, popř. se v nich využívá pomocných funkcí naprogramovaných v céčku či C++ (je však možné provést vazbu i na další programovací jazyky). Velkou předností systému LÖVE je jeho snadná použitelnost, spočívající zejména v přehledném aplikačním programovém rozhraní (API) jednotlivých knihoven přítomných v tomto systému i jednoduché a snadno použitelné syntaxi jazyka Lua a jeho dynamickém typovém systému. Poněkud problematická je zpětná nekompatibilita se staršími verzemi LÖVE, což může vadit zejména studentům hledajícím inspiraci na Internetu (některé příklady totiž zkrátka nebudou funkční).
Obrázek 24: Framework LÖVE ve chvíli, kdy není načtena žádná hra (tento animovaný obrázek se mění v různých verzích knihovny LÖVE).
Samotný systém LÖVE interně využívá (tj. volá funkce) několika céčkových a C++ knihoven, především pak knihovny boost (obecné algoritmy pro aplikace vytvářené v C++), SDL (nastavení grafických režimů, přepnutí do režimu celé obrazovky, čtení stavu klávesnice, myši a joysticku), SDL_mixer (podpora hudby a zvuků), OpenGL (2D grafika, double buffering), DevIL (práce s rastrovými obrázky) a FreeType 2 (vykreslování písma), avšak vývojář, který pomocí LÖVE vytváří hry či jiné interaktivní aplikace s 2D grafikou, hudbou a zvuky, je od těchto knihoven zcela odstíněn aplikačním programovým rozhraním systému LÖVE a přijde tak do styku pouze se skripty napsanými v programovacím jazyku Lua. To je pro zamýšlené účely ideální stav, který však může přinášet problémy u rozsáhlejších her či dalších typů aplikací.
Obrázek 25: Ukázka blendingu v systému LÖVE.
11. Pygame
I přesto, že je programovací jazyk Lua při tvorbě počítačových her úspěšně používán přes dvacet let, objevují se i nové knihovny a enginy, které i v této oblasti využívají jiné vyšší (řekněme poněkud nepřesně skriptovací) programovací jazyky. Za zmínku zcela jistě stojí projekt Pygame, což je knihovna určená pro programovací jazyk Python, která interně volá funkce nativní knihovny SDL a několika dalších podpůrných knihoven. Myšlenka, na níž je Pygame postavena, je v mnoha ohledech podobná myšlence výše zmíněného systému LÖVE – implementace nízkoúrovňových operací nechť je vytvořena odborníky v programovacích jazycích C a C++; pokud budou tyto operace implementovány dostatečně rychle, je již možné zbytek hry naprogramovat ve vysokoúrovňovém jazyku Python. A ukazuje se, že je tato myšlenka – a obecně systém rozdělení aplikace mezi dva programovací jazyky (kompilovaný a skriptovací) – poměrně úspěšná, neboť v Pygame již vzniklo mnoho kvalitních her.
Obrázek 26: Logo knihovny Pygame.
12. Pyglet
Výše stručně popsaná knihovna Pygame je kvůli své relativně těsné vazbě na nativní knihovnu SDL určena především pro tvorbu 2D her, tj. různých strategií (realtime i tahových), plošinovek, RPG apod. Ve chvíli, kdy je zapotřebí vytvořit plnohodnotnou trojrozměrnou hru, je možné namísto Pygame použít další knihovnu určenou pro programovací jazyk Python. Tato knihovna se jmenuje Pyglet a mezi její základní vlastnosti patří vazba na knihovnu OpenGL a tedy i nepřímo na grafické akcelerátory. Kromě vazby na knihovnu OpenGL však v Pyglet mohou programátoři najít i další zajímavé moduly, například pro práci s hudbou a se zvuky (ALSA, OpenAL, DirectSound), podporu pro různé formáty uložení hudby (zejména OGG/Vorbis), podporu pro načítání a zobrazování animací uložených v DivX, AVI, MPEG, H.263 atd.
Obrázek 27: Logo knihovny Pyglet.
13. Pygame Zero
Nyní se konečně dostáváme k popisu projektu Pygame Zero. Již podle názvu tohoto projektu je možné usoudit, že je postaven na bázi knihovny Pygame zmíněné ve dvanácté kapitole. Nejedná se ovšem o doplnění této knihovny o nové funkce nebo celé třídy, ale je tomu vlastně úplně naopak – okolo Pygame je vytvořeno rozhraní dostupné uživatelům a to je navrženo takovým způsobem, aby obsahovalo jen nejnutnější prvky a navíc aby bylo dobře pochopitelné a použitelné. Principy, na jakých je tento projekt postaven, jsou napsány na stránce https://pygame-zero.readthedocs.io/en/stable/principles.html. Jedná se – alespoň podle mého názoru – o poměrně dobrý přístup, který zajišťuje, že celý projekt Pygame Zero bude velmi dobře uchopitelný, nebudou se používat „magické“ funkce ani konstanty a i chybová hlášení by měla dávat dobrý smysl (i když zaručit dobrá chybová hlášení je pro projekt tohoto typu, navíc běžící na otevřené a široce konfigurovatelné platformě PC, velmi složité, snad i nemožné).
Obrázek 28: Logo projektu Pygame Zero.
V některých ohledech se Pygame Zero přibližuje projektu LÖVE zmíněného výše – i zde se pro spouštění vytvořených programů používá speciální nástroj, který „obaluje“ vlastní interpret programovacího jazyka Python; spustit je možné i prázdný projekt (zatímco v Pygame je nutné vytvořit alespoň minimální kostru projektu), součástí projektu jsou i všechny potřebné zdroje (sprity, …) atd. Podrobnosti budou ukázány v dalším textu a ve větším rozsahu i v navazujícím článku.
V Pygame Zero se využívají tyto koncepty používané v počítačové grafice, ve hrách i interaktivních aplikacích:
- Sprity, zde představované instancemi třídy Actor.
- Callback funkce volané při vzniku událostí (kliknutí tlačítkem myši atd.).
- Úlohy s naplánovaným časem spuštění.
Programový kód bude vystavěn zejména na callback funkcích (kterým můžeme říkat obslužné rutiny událostí – handlery). Pokud handler pro nějakou událost nebude existovat, provede se výchozí akce (většinou žádná akce, výjimkou je překreslení obrazovky atd).
Obrázek 29: Ukázka 3D scény s několika sprity (snad nemusím psát, odkud ten screenshot pochází).
14. Instalace Pygame Zero
Instalace projektu Pygame Zero je poměrně snadná, protože balíček s tímto projektem je dostupný v repositáři Python Package Index (PyPI). K instalaci tedy postačuje použít příkaz pip, resp. pip3, podle toho, jakým způsobem máte nainstalován Python 3:
$ pip3 install --user pgzero
Průběh instalace se odlišuje podle toho, jaké závislé balíčky již máte nainstalovány a jaké musí být doinstalovány (popř. v některých případech přeloženy):
Collecting pgzero Downloading https://files.pythonhosted.org/packages/48/e5/e5f14292373cb5fc7539aa01307b184c1e3c954d68945d8c44778669dd82/pgzero-1.2-py3-none-any.whl (69kB) 100% |████████████████████████████████| 71kB 447kB/s Collecting pygame<2.0,>=1.9.2 (from pgzero) Downloading https://files.pythonhosted.org/packages/8e/24/ede6428359f913ed9cd1643dd5533aefeb5a2699cc95bea089de50ead586/pygame-1.9.6-cp36-cp36m-manylinux1_x86_64.whl (11.4MB) 100% |████████████████████████████████| 11.4MB 105kB/s Requirement already satisfied: numpy in ./.local/lib/python3.6/site-packages (from pgzero) Installing collected packages: pygame, pgzero Collecting pgzero Using cached https://files.pythonhosted.org/packages/48/e5/e5f14292373cb5fc7539aa01307b184c1e3c954d68945d8c44778669dd82/pgzero-1.2-py3-none-any.whl Requirement already satisfied: numpy in ./.local/lib/python3.6/site-packages (from pgzero) Collecting pygame<2.0,>=1.9.2 (from pgzero) Using cached https://files.pythonhosted.org/packages/8e/24/ede6428359f913ed9cd1643dd5533aefeb5a2699cc95bea089de50ead586/pygame-1.9.6-cp36-cp36m-manylinux1_x86_64.whl Installing collected packages: pygame, pgzero Successfully installed pgzero-1.2 pygame-1.9.6
Kontrola, do jakého adresáře se nainstaloval spustitelný soubor pgzrun:
$ which pgzrun /home/ptisnovs/.local/bin/pgzrun
Nyní se můžeme pokusit o spuštění tohoto souboru:
$ pgzrun --help pygame 1.9.6 Hello from the pygame community. https://www.pygame.org/contribute.html Usage: pgzrun [options] Options: -h, --help show this help message and exit
15. Vytvoření a spuštění prázdného projektu
Podívejme se nyní na kostru projektu vytvořeného takovým způsobem, aby byl spustitelný přes příkaz pgzrun. Při použití mnoha jiných knihoven pro 2D či 3D grafiku je očekáván alespoň nějaký inicializační kód (otevření okna, vymazání obsahu okna, vstup do smyčky událostí), ovšem v případě Pygame Zero je prázdný (nicméně funkční!) projekt skutečně minimalistický – může se jednat o prázdný soubor!
Ostatně můžeme si to velmi snadno ověřit vytvořením prázdného zdrojového souboru:
$ touch intro.py
Který následně spustíme přes pgzrun:
$ pgzrun intro.py pygame 1.9.6 Hello from the pygame community. https://www.pygame.org/contribute.html
Otevřít by se mělo prázdné okno představující běžící aplikaci:
Obrázek 30: Okno projektu po jeho spuštění. Jedná se o okno vyplněné černou barvou.
16. Vyplnění pozadí určenou barvou
Předchozí projekt byl sice plně funkční, ale poněkud fádní. Pokusme se tedy vytvořit skript se skutečným kódem. V něm budeme specifikovat požadované rozměry okna 480×480 pixelů a zajistíme explicitní vymazání obsahu tohoto okna. Rozměry se specifikují v proměnných nazvaných WIDTH a HEIGHT a vykreslovací rutina se zapisuje do funkce pojmenované draw (všechny tři názvy musí být dodrženy):
WIDTH = 480 HEIGHT = 480 def draw(): screen.clear()
Obrázek 31: Okno projektu po jeho spuštění. Opět se jedná o okno vyplněné černou barvou.
V případě, že budeme chtít, aby pozadí okna mělo odlišnou barvu, je nutno namísto metody screen.clear() zavolat metodu screen.fill(), které se předá trojice hodnot 0–255 s kódem barvy:
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) def draw(): screen.fill(BACKGROUND_COLOR)
Obrázek 32: Okno projektu po jeho spuštění. Nyní je okno vyplněné určenou barvou pozadí.
Pokud je koncept barvového prostoru RGB pro začátek příliš složitý, je možné namísto trojice použít jméno barvy ve formě řetězce:
WIDTH = 480 HEIGHT = 480 def draw(): screen.fill("darkgreen")
17. Vykreslení spritů do 2D scény
Nyní již umíme použít alespoň základní vykreslovací příkaz – vymazání obrazovky, popř. její vyplnění konstantní barvou. Poněkud komplikovanější situace nastane ve chvíli, kdy je zapotřebí původně statickou 2D scénu „rozpohybovat“, tj. vložit do ní různé pohyblivé objekty. Modifikace 2D scény pixel po pixelu v naprosté většině případů nepřichází v úvahu, protože se jedná o velmi pomalou operaci. Podobně pomalé je většinou i vykreslování základních geometrických tvarů, které sice může být v některých případech realizováno na grafickém akcelerátoru, ovšem v případě knihovny Pygame Zero (které tyto rutiny obsahuje!) nemáme jistotu, že nedojde k softwarovému (a tedy náležitě pomalému) vykreslení. Zbývá nám tedy jediné – zaměřit se na využití pohybujících se rastrových objektů neboli spritů. V tomto ohledu nám knihovna Pygame Zero může pomoci, protože programátorům nabízí objekty typu Actor.
V dalším demonstračním příkladu je třída Actor použita – je vytvořena její instance a obrázek spritu je načten ze souboru images/sprite1.png (images je implicitní název adresáře pro obrázky). Dále nastavíme souřadnice spritu tak, aby jeho střed ležel přesně uprostřed okna, tj. na pozici [240, 240]. Sprite je vykreslen metodou draw():
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()
Obrázek 33: Sprite vykreslený přesně uprostřed obrazovky.
Existuje ještě jedna varianta, a to přímé vykreslení obrázku do scény (zde se využívá faktu, že je obrázek uložen do cache a nemusí být neustále načítán). Nevýhodou je, že operace typu blit vyžaduje zadání levého horního rohu spritu, takže tento není vycentrován:
WIDTH = 480 HEIGHT = 480 BACKGROUND_COLOR = (0, 0x80, 0x80) def draw(): screen.fill(BACKGROUND_COLOR) screen.blit("sprite1.png", (240, 240))
Obrázek 34: Obrázek vykreslený tak, že jeho levý horní roh leží přesně uprostřed obrazovky.
18. Vykreslení rastrového obrázku na pozadí
Podívejme se ještě na jednu možnost, jak do scény vykreslit obrázek. Tentokrát použijeme objekt images, jehož atributy jsou všechny obrázky uložené v adresáři images (bez nutnosti jejich explicitního načítání – vše je provedeno automaticky). Obrázek uložený v souboru „plasma.png“ má rozměry 480×480 pixelů a přesně tedy odpovídá rozměrům okna:
WIDTH = 480 HEIGHT = 480 def draw(): screen.blit(images.plasma, (0, 0))
Výsledek:
Obrázek 35: Obrázek na pozadí okna.
Obě možnosti můžeme zkombinovat, tedy vykreslit na pozadí bitmapu a nad ni (překreslit) sprite:
WIDTH = 480 HEIGHT = 480 sprite = Actor("sprite1.png") sprite.pos = (240, 240) def draw(): screen.blit(images.plasma, (0, 0)) sprite.draw()
Obrázek 36: Obrázek na pozadí okna přes který je nakreslen sprite.
Příště se pokusíme celou scénu rozpohybovat, což bude opět otázka pouze několika programových řádků.
#!/usr/bin/env python # Vytvoreni textury typu "plasma" from PIL import Image from random import random import palette_blues import palette_greens import palette_gold import palette_ice import palette_mandmap import numpy as np import math # textura by mela byt ctvercova a jeji sirka i vyska by mela byt # mocninou cisla 2 IMAGE_WIDTH = 480 IMAGE_HEIGHT = 480 def random_gauss(): ''' Vygenerovani nahodneho cisla v rozsahu 0..1 s pribliznym Gaussovym rozlozenim ''' N = 50 sum = 0.0 for i in range(N): sum += random() return sum/N def compute_min_max(bitmap, width, height): # pro prepocet intenzit pixelu min = float("inf") max = float("-inf") # ziskani statistiky o obrazku - minimalni a maximalni hodnoty for j in range(height): for i in range(width): z = bitmap[j][i] if max < z: max = z if min > z: min = z return min, max def convert_to_image(bitmap, image, width, height, palette): print("contrast adjustment") min, max = compute_min_max(bitmap, width, height) k = 255.0 / (max - min) # zmena kontrastu a kopie bitmapy for y in range(height): for x in range(width): f = float(bitmap[y][x]) f -= min f *= k i = int(f) & 255 color = (palette[i][0], palette[i][1], palette[i][2]) image.putpixel((x, y), color) # h ... Hurstuv exponent # n ... pocet koeficientu spektralni syntezy def spectral_synthesis(image, palette, n, h): width, height = image.size # rozmery obrazku bitmap = np.zeros([height, width]) A = np.empty([n//2, n//2]) # koeficienty Ak B = np.empty([n//2, n//2]) # koeficienty Bk beta = 2.0 * h + 1 # promenna svazana s Hurstovym koeficientem print("calculate coefficients") # vypocet koeficientu Ak a Bk for j in range(n//2): for i in range(n//2): rad_i = pow((i+1), -beta/2.0)*random_gauss() rad_j = pow((j+1), -beta/2.0)*random_gauss() phase_i = 2.0*math.pi*random() phase_j = 2.0*math.pi*random() A[j][i] = rad_i*math.cos(phase_i)*rad_j*math.cos(phase_j) B[j][i] = rad_i*math.sin(phase_i)*rad_j*math.sin(phase_j) print("plasma synthesis") # vygenerovani plasmy for j in range(height): for i in range(width): z = 0 # inverzni Fourierova transformace for k in range(n//2): for l in range(n//2): u = (i-n/2)*2.0*math.pi/width v = (j-n/2)*2.0*math.pi/height z += A[k][l]*math.cos(k*u+l*v)+B[k][l]*math.sin(k*u+l*v) bitmap[j][i] = z convert_to_image(bitmap, image, width, height, palette) image = Image.new("RGB", (IMAGE_WIDTH, IMAGE_HEIGHT)) spectral_synthesis(image, palette_greens.palette, 4, 0.5) image.save("patternD_plasma1.png") spectral_synthesis(image, palette_blues.palette, 10, 0.5) image.save("patternD_plasma2.png") spectral_synthesis(image, palette_mandmap.palette, 5, 0.1) image.save("patternD_plasma3.png") spectral_synthesis(image, palette_mandmap.palette, 5, 1.0) image.save("patternD_plasma4.png") spectral_synthesis(image, palette_gold.palette, 15, 0.5) image.save("patternD_plasma5.png") spectral_synthesis(image, palette_ice.palette, 15, 0.8) image.save("patternD_plasma6.png")
19. Repositář s demonstračními příklady
Zdrojové kódy všech dnes 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/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