Rychlá navigace:
Stránka byla naposled aktualizována ve středu 6. dubna 2022 navečer.
Sound.PlayMusic(...)
Na některých lekcích kroužku budeme, jako jedno z témat, děti učit programovat v jazyce Small Basic. Příkazy se píšou anglicky, ale veškerá nápověda je přeložena do češtiny, a jedná se o programovací jazyk pro děti. Heslo jazyka je "Every kid can code!", tedy "Každé dítě zvládne programovat!" a my tomu rozhodně věříme. Na této stránce najdete ke každé lekci naše zdrojové kódy ke stažení. Ty zahrnují celý obsah lekce, kterou jsme s dětmi absolvovali. Následuje pak popis jednotlivých témat, které byly obsahem lekce.
Nemá smysl číst kódy zvlášť nebo popis na této stránce zvlášť. Ideální je stáhnout si Small Basic, v něm si naše kódy otevřít, otevřít si nový prázdný program a zkoušet si programovat k tomu. Čili číst náš kód, zkoušet si napsat něco podobného, a pro popis kódu se dívat na tuto stránku. Kód si je vhodné spustit, aby šlo vidět, co ten kód dělá, a až pak se podívat, jakými příkazy toho bylo docíleno.
Popisy funkcionalit na stránce píšeme jako souvislý text, aby sloužil jako dovysvětlení/připomenutí problematiky pro ty, kdo na kroužku něco nestihli, nepochytili či na krožku vůbec nebyli. Přehled příkazů a vlastností na jednotlivých objektech zobrazí nápovědní panel přímo ve Small Basicu, takže rychlý přehled by nemělo smysl tu mít.
Po každé lekci navíc publikujeme "úkol na doma". Je tam vždy několik zadání, které si můžete zkusit naprogramovat. Pokud se zadaří, pošlete nám řešení na email, nebo jej přineste na další kroužek. Máme nachystané odměny, pro lepší motivaci :)
AltGr = pravý Alt
Znak | Poznámka | Klávesová zkratka |
---|---|---|
" | (Dvojité) uvozovky - textová hodnota | Shift + ů |
< a > | Většítko a menšítko, jinak také špičaté závorky | AltGr + , a AltGr + . |
[ a ] | hranaté závorky - přístup do pole | AltGr + F a AltGr + G |
Pokud nemáte numerickou klávesnici, hodí se také: | ||
* | hvězdička, asterisk (neplést s Asterixem ;)) - násobení | AltGr + - |
/ | (dopředné) lomítko, lomeno - dělení | Shift + ú |
\ | zpětné lomítko, backslash - oddělovač složek u cest k souborům | AltGr + q |
Pár "užitečných" znaků, co se můžou hodit: | ||
@ | zavináč | AltGr + V |
# | křížek, hash kříž, hashtag | AltGr + X |
& | ampersand, and, anglické a | AltGr + C |
Když programujeme, vytváříme "Zdrojový kód", což je obyčejný textový soubor, který má příponu ".sb". Ten se dá otevřít kdekoli, nejen v softwaru Small Basicu, ale třeba i v poznámkovém bloku a tak podobně - je to jen text. Small Basic nám ho ale vykreslí hezky obarvený, aby se nám přehledně programovalo, ale také nám umí program spustit.
Když program spustíme, Small Basic software nejprve udělá tzv. překlad, neboli kompilaci, našeho zdrojového kódu. Procesor počítače totiž nerozumí přímo Small Basicovému kódu, takže ho software vezme a přechroustá tak, aby mu procesor rozumněl. Tím nám ve složce, ve které je náš zdrojový kód (soubor ".sb"), vzniknou nějaké další soubory.
Řekněme, že jsme vytvořili zdrojový kód "kalkulacka.sb". Když jej spustíme, ve složce nám přibudou následující soubory:
SmallBasicLibrary.dll
. Ten se nám
při spuštění ze softwaru ve složce vždy objeví, takže program běží. Pokud tam soubor nebude, náš program se vůbec nespustí!
Bohužel se nezobrazí ani žádná chybová hláška.
Pokud tedy budete chtít dát váš program třeba kamarádovi nebo tak, a nechcete mu dávat váš zdrojový kód (aby vám program neukradl
nebo proto, že vůbec neumí programovat, Small Basic nemá naistalovaný a tímpádem by mu byl k ničemu), můžete mu dát váš ".exe" soubor,
ale vždy i SmallBasicLibrary.dll
, jinak si program nebude moci spustit!
Programy takto vytvořené běží pouze ve Windows s nainstalovaným .NET Framework 4.5.
Zkoušejte si určitě programovat, i proto publikujeme úkoly na doma.
Instalace Small Basicu - ideálně z oficiální webové stránky www.smallbasic.com
stáhněte instalátor přes tlačítko Download. Během instalace pak zvolte češtinu. Jedná se o verzi 1.2
,
na Microsoft Store je sice k dispozici verze 1.3
, ovšem to je pouze port, který ještě nepodporuje
všechno, co verze 1.2
- proč je to značené takhle blbě je nám také záhadou :D
Je potřeba počítač s Windows a s nainstalovaným .NET FrameWork 4.5, ten by měla instalačka zvládnout stáhnout a poprosit
vás o případnou doinstalaci. Je to běžná součást Windows, a dost pravděpodobně ji již budete mít.
Pokud nemáte Windows, je možné programovat i přímo z prohlížeče. Na stránce z odkazu výše jen místo Download zvolíte
Start coding online a po delším načítání se otevře webový editor. Nevýhoda je, že Není tak pohodlný, nefungují
některé klávesové zkratky a je pouze anglicky.
Na internetu existuje k programování velká spousta věcí. Jasně, většina z nich je pro profesionální programátory, která třeba není ani zábavná a nebudete jí rozumnět, ale nezoufejte, když na něco dobrého narazíme, určitě vám o tom řekneme a dáme odkaz.
Za shlédnutí jistě stojí seriál České Televize DATOVÁ LHOTA,
na kterém mimochodem spolupracovali výborní programátoři a pedagogové informatiky Pavel Ježek a Cyril Brom z Matematicko Fyzikální Fakulty
na Karlově Univerzitě v Praze, kde také studují lektoři tohoto kroužku ;)
Seriál (včetně bonusů a bonusové počítačové hry) krásně představuje, jak zhruba (v představě) funguje uvnitř počítač.
To se nám bude hodit pro pochopení toho, jaktože se věci v našem programovacím jazyce chovají tak, jak se chovají. Seriál doporučujeme
zkouknout, je to i výborná zábava :)
Zde jsou všechny kódy, jak postupně vznikají. Některé vznikly přímo na lekcích, jiné jsme připravili mimo kroužek jako další zdroj vědomostí.
Ukázky:
Úkoly na doma včetně řešení:
Přehled pojmenovaných Barev, které je možno používat v objektu GraphicsWindow
.
Dále oficiální stránka jazyka Small Basic s instalátorem, online
prostředím a tutoriály v anglickém jazyce,
a také oficiální dokumentace
jazyka Small Basic - také v anglickém jazyce.
Seriál ČT :D Datová Lhota.
Soubory se zdrojovým kódem ke stažení:
If ... Then - ElseIf ... Then - Else - EndIf
Prošli jsme úplný úvod k programování. Jak se zachází s IDE a co kde najít na klávesnici.
Hello world, co dělá kód a základy práce s textovým oknem - objekt TextWindow
. Počítání s čísly a
"sčítání textu" - tedy lepení textu za sebe. Nakousli jsme podmínky a ukázali jsme si kalkulačku.
Naučili jsme se, co je to komentář a k čemu slouží v kódu. Naučili jsme se, co je to proměnná, jak ji pojmenovat a použít jako součást výrazů. Viděli jsme poprvé Small Basicový objekt a zavolali na něm nějaké příkazy.
Soubory se zdrojovým kódem ke stažení:
While ... - EndWhile
For ... To ... Step - EndFor
Prošli jsme smyčky, a díky smyčce jsme vylepšili kalkulačku, která teď umí počítat dokola. Také jsme nakousli grafické okno a kreslení želví grafiky do něj. Poprvé jsme viděli koncept vlastnosti, tedy speciální proměnné na objektu značené v nápovědě paletou místo pastelky.
Dokončili jsme želvu. Probrali jsme přímé pohybování přes Move()
a Turn()
,
ukázali si spirálu a tím procvičili smyčky. Jelikož je konec pololetí, nové téma jsme nezačali, ani jsme nedávali další úkol na doma.
Soubory se zdrojovým kódem ke stažení:
Na začátku lekce jsme trénovali programátorské dovednosti na příkladu se šachovnicí. V podobném duchu se točí
úkol na doma - a je, myslíme, jednodušší, než samotná šachovnice.
Dále jsme se začali věnovat kreslení úseček přímo pomocí objektu grafického okna, a začali si psát vlastní malování.
Soubory se zdrojovým kódem ke stažení:
Domluvili jsme se, že do příště zkusíte ještě mrknout na úkol na doma č.3, viz minulá lekce. Úkol na příště je podívat se na poslední verzi Malování a pochopit, jak se do ní dodělalo gumování pomocí pravého tlačítka myši.
Probrali jsme si Malování, myšové události Grafického okna a samotný objekt Mouse reprezentující Myš. Sám o sobě toho moc neumí, protože nejdůležitější je myš při
ovládání aplikace s Grafickým oknem, které nám poskytne souřadnice myši vůči sobě, a také myšové události. Objekt myš nám ale poví stav tlačítek, to je to hlavní.
Naučili jsme se práci s barvami, je to celkem jednoduché. TADY JE PŘEHLED VŠECH BAREV - s překladem, jinak je to seznam z oficiální
webové stránky Microsoftu.
Barvu nastavujeme pozadí a peru, příště si ukážeme ještě štetec.
A znovu jsme se mrkli na komentáře, k čemu v kódu slouží a jak je psát.
Soubory se zdrojovým kódem ke stažení:
Podívali jsme se na kreslení geometrických útvarů. Zopakovali jsme barvy a souřadný systém. Zkoušeli jsme tvary animovat.
Soubory se zdrojovým kódem ke stažení:
Shapes
- další funkceNa začátku jsme diskutovali o významu slova konkurence, a hlavně jaký význam má ve světě programování. V reálném programátorství má dalekosáhlý význam, protože provází celé odvětví tzv. asynchonního programování. Toho se zlehka dotýká i programování ve Small Basicu díky událostem. Shrnutí našich poznatků na téma konkurence je u událostí uvedeno.
Probrali jsme téma - herní smyčka. To nám zabralo většinu kroužku, ve zbytku lekce jsme se ještě mrkli na objekt Shapes
, konkrétně
na příkazy HideShape(...)
a ShowShape(...)
, Rotate(...)
,
Zoom(...)
a SetOpacity(...)
. A také jsme si řekli o speciální barvě
"Transparent"
, která nám umí udělat průhledný štětec či pero, abychom měli útvary objektu Shapes
jen rámeček či jen výplň.
To vše by se vám mohlo hodit na řešení úkolu č. 4, chceme po vás jen, ať si "pohrajete s tvary" a vyrobíte nějaký obrázek. Víc toho není a vyzkoušíte si důležitou věc. Vzhledem k tomu, že úkol na dnešek nikdo nedonesl, dáme vám na něj ještě týden.
Co se týče tématu herní smyčky, ještě se k němu určitě vrátíme. Představená hra je možná (programátorsky) složitá, takže třeba ještě na závěrečný program vymyslíme nějakou jednodušší, to se však ještě dohodneme.
Soubory se zdrojovým kódem ke stažení:
Probrali jsme, jak je v počítači uložen text (jednotlivé znaky - písmena, číslice, tečky, čárky apod. jsou uloženy za sebou v paměti).
S textem pak umíme pracovat, máme k tomu příkazy na objektu Text
, které nám v tom pomohou. Vždycky
musíme pracovat po jednotlivých znacích (písmenkách).
K tomu jsme se na chvíli pobavili, jak pracuje počítač a srovnání s člověkem, a to, jak dělá chyby člověk a jak počítač. A jak počítač
vnímá text a proč je práce s ním taková podivná a "matematická".
Dále jsme probrali objekt Controls
. Pracuje se s ním podobně, jako se Shapes
,
jen nám nereprezentuje geometrické útvary, ale tzv. "kontrolky", neboli interaktivní prvky, se kterými může uživatel interagovat. Jedná se
o tlačítka (Buttony) a textová pole (TextBoxy). Tlačítka mohou mít na sobě text a uživatel je může mačkat levým tlačítkem myši, textová pole
text obsahují, může jej do nich napsat uživatel pomocí klávesnice, a můžeme jej do nich vkládat i programátorsky.
Samozřejmě jsme pracovali s grafickým oknem, připomněli jsme příkaz ShowMessage(...)
, který uživateli ukáže
informační okénko se zprávou, které musí napřed odkliknout, než může dál pracovat s hlavním oknem.
Na závěr jsme se domluvili, že vám opět dáme ještě týden na to donést nějaký ten obrázek v rámci úkolu na doma číslo 4. Zároveň zadáváme
úkol č. 5 - ten je určitě na příště. Publikovali jsme kód kalkulačky pomocí Controls
, a vaším úkolem je si jej
stáhnout a pochopit, jak pracuje. Měly by k tomu stačit znalosti z dnešního kroužku. Ideální by samozřejmě bylo, abyste si kalkulačku
(nebo podobnou aplikaci) vytvořili samostatně, ale nechceme to dávat za úkol. Kdo by se do toho pustil, odměna ho nemine :)
Soubory se zdrojovým kódem ke stažení:
Kompletně jsme ukázali práci s textem v grafickém okně. Text může vykreslovat Grafické okno a máme také
tvar text, kterému můžeme nastavovat text i po vytvoření, takže je programátorsky interaktivní, a stojí tak
na pomezí mezi útvarem a ovládacím prvkem. Jinak se dá samozřejmě ovládat stejně, jako všechny ostatní útvary
objektu Shapes
. Dále máme k dispozici text v TextBoxech objektu
Controls
, který nám může měnit i uživatel.
Druhá část práce s textem je ostylovat ho. Probrali jsme, že styl textu nám řídí vlastnosti grafického okna,
je možné nastavit barvu, jakým písmem je text napsán (tzv. řez písma), jak je text velký, a jestli má být text
tučný či našikmený (tzv. kurzíva neboli italika). Tyto styly se aplikují na text vykreslované oknem, na textový
útvar, TextBoxy a také tlačítka objektu Controls
!
Na konci hodiny jsme začali práci s polem, podrobněji příště.
Byl zadán také pátý úkol na doma, a je trochu podobný tomu čtvrtému, s využitím znalostí o kreslení textu z dneška, takže věříme, že se vám bude dařit!
Soubory se zdrojovým kódem ke stažení:
GraphicsWindow
+ jako tvar objektu Shapes
Sound
Úkol na doma č.5 jsem minule zapomněl nahrát na internet, takže na něj máte ještě týden.
Dalším úkolem je
podívat se na objekt Clock
a práci s časem, posloužit by k tomu měl ukázkový kód 31.
Tak na to, prosím, nezapomeňte :) Zadáváme i úkol č. 6, který je ale zcela navíc - jedná se o úkol na procvičení polí.
Kompletně jsme ukázali práci s obrázky v grafickém okně. Obrázky lze vykreslovat přímo Grafickým oknem,
nebo jako útvar objektu Shapes
. Práce je trochu rozdílná, u grafického okna buď vykreslíme přímo,
nebo obrázku dáme jinou velikost. Pokud přitom nechceme, aby se obrázek zplácnul či roztáhl, použijeme výpočet poměru stran,
a rozměry dopočítáme (chceme-li mít danou šířku, vydělíme ji poměrem a máme výšku. Chceme-li mít danou výšku, vynásobíme ji
poměrem a máme šířku). Pokud vykreslovaný obrázek použijeme více, než jednou, nejprve ho načteme do objektu ImageList
.
Dále jsme si ukazovali objekt Sound
, který umožňuje přehrávat zvuky. Zvuky přehráváme jako "Play", pak příkaz okamžitě
končí (podobně, jako Shapes.Animate(...)
) a můžeme dělat další kód, zatímco zvuk hraje.
Nebo lze použít variantu "PlayAndWait", pak se na příkazu čeká, než zvuk dohraje. Pomocí PlayMusic(...)
lze přehrávat
piánové skladby jedním prstem zapsané v textovém formátu. Podívejte se do dokumentace níže, je to tam popsáno a hlavně tam najdete ukázkový program.
Na konci hodiny jsme ukázali podrobněji práci s polem. Ne všechno jsme stíhali, pole toho umí daleko více, než jsme ukazovali, takže se určitě podívejte
na ukázkový zdrojový kód 30, kde je vše vidět. Také je to popsáno v dokumentaci, plus připravíme dolů do sekce doplňujících poznatků povídání o objektu
Array
, který umožňuje dělat s polem ještě daleko pokročilejší věci.
DOKUMENTACE ZA TUTO A MINULÉ DVĚ LEKCE NENÍ BOHUŽEL JEŠTĚ DOPLNĚNA, ALE VŠE BY SNAD MĚLO JÍT POCHOPIT Z UKÁZKOVÝCH ZDROJOVÝCH
KÓDŮ. OMLOUVÁM SE ZA NEPŘÍJEMNOSTI, ALE MÁM BOHUŽEL NÁROČNÝ TÝDEN A NESTÍHÁM. -Kryštof
Doplněno - Pole, Objekt Program, Částečně objekt Sound
Bude doplněno - Objekt Controls, Vykreslování textu, Objekt Text, Vykreslování obrázků a Objekt ImageList, Zbytek Objektu sound, Objekt Clock, pokročilejší
práce s objektem Text do sekce doplňujcích poznatků.
Soubory se zdrojovým kódem ke stažení:
Komentář v kódu napíšeme za znak apostrof: a = 1'zápis 1 do proměnné a
Objekty, jejich příkazy, řídicí struktury a jména proměnných nám program napovídá (tomu se říká Intellisense) - vyvoláme
jej stiskem Ctrl + Mezerník. Listovat v něm můžeme šipkami, vložení nalistovaného kódu provedeme pomocí Enter. Také nám vyskakuje, když něco píšeme,
a napovídá podle toho, co jsme již napsali. Nemusíme tedy písmenko po písmenku vypisovat příkaz celý, ale napovídané části si nechat doplnit. Velmi to šetří čas strávený psaním kódu,
tak si na to zkuste zvyknout.
Proměnná je jakýsi šuplíček, který nám uchovává hodnotu - číslo nebo text. Šuplíček má své jméno, díky kterému do něj můžeme kdykoli nakouknout (čtení hodnoty proměnné)
nebo do něj vložit nový obsah (přiřazení hodnoty do proměnné). Pokud do nějakého výrazu (viz dále
Text zapíšeme mezi uvozovky - "textová hodnota"
. Pokud bychom na to zapomněli, Small Basic by za naším textem hledal názvy proměnných.
Desetinná čísla nepíšeme s čárkou, ale s tečkou! Tedy jednaPolovina =
0.5
Domluvili jsme se, že pro přehlednost budeme proměnné pojmenovávat s malým písmenkem na začátku. Název může být český, ale neměl by nikdy
obsahovat diakritiku! (háčky a čárky)
Spávná jména jsou tedy promenna
, a
, cislo1
, pocetKilometru
Kód v jazyce SmallBasic se vykonává řádek po řádku. Přeskakují se prázdné řádky a Komentáře - ty nám editor
vykresluje zeleně a kurzívou. Vše ostatní je kód.
Kód na daném řádku má několik podob:
=
rovná se. V nápovědním panelu je proměnná značena symbolem pastelky. Jedná-li se o proměnnou, která patří nějakému
objektu, mluvíme o ní jako o "Vlastnosti" daného objektu, jinak se s ní ale pracuje stejně. V nápovědním panelu má symbol malířské palety.TextWindow
. Název objektu nám editor
vykresluje tmavě tyrkysově, v nápovědnám panelu je značen symbolem oranžové krabice. TextWindow.WriteLine("Ahoj, světě!")
.
Tedy jsme napsali název_objektu tečka název_příkazu
otevírací_kulatá_závorka hodnota_parametru zavírací_kulatá_závorka. If
. Editor nám klíčová slova, která strukturu
tvoří, vykresluje tučně fialově.
Všechny struktury mají ukončovací klíčové slovo, které začíná End
, například EndIf
.Sub
zavoláme
úplně stejně, jako příkaz objektu - pomocí názvu a kulatých závorek. Naše podprogramy nemají žádné parametry, takže závorky zůstanou vždy prázdné. Navíc název
podprogramu zůstane vykreslen černou barvou.
=
rovná se do ní můžeme
vložit hodnotu, ale touto hodnotou je název subrutiny, jež má sloužit jako obsluha události. Pozor - název nepíšeme do ""
uvozovek,
ani za něj nepíšeme závorky - není to totiž ani textová hodnota, ani se podprogram nesnažíme volat.
Ještě jednou se podíváme na místa, kde do kódu vstupuje hodnota (text či číslo) nebo proměnná/vlastnost. Ta místa jsou přiřazení do proměnné/vlastnosti nebo parametr příkazu.
Kromě toho, že tam dáme přímo jednu hodnotu nebo jedno jméno proměnné, můžeme jich tam dát více, a spojit pomocí operátorů.
To znamená, že do té proměnné nebo parametru doputuje výsledek, který ten operátor spočítá.
Když máme text, zajímá nás operátor plus +
. Ten jednoduše spojí texty k sobě, přilepí je za sebe. Tomu se někdy říká konkatenace.
Když máme čísla, máme k dispozici plus, mínus, krát a děleno +, -, *, /
, a ty prostě počítají s čísly, jsou to běžné početní operace.
Složitější početní operace jsou k dispozici jako příkazy objektu Math
("matematika").
Kromě klasických proměnných lze použít také pole. Jako jsme proměnné přirovnali k šuplíku, který je pojmenovaný, a lze do něj něco uložit, tak pole
je pojmenovaná Skříň s takovýmito šuplíky. A těch šuplíků v ní může být, kolik chce. Pokud máme nějakou prázdnou proměnnou (obsahuje hodnotu
""
), je to vlastně zároveň pole, které neobsahuje žádné věci.
Jak tedy "do skříně" (do pole) přistupujeme? Dělá se to přes hranaté závorky, do kterých napíšeme tzv. "index", což je hodnota, obvykle tedy číslo,
pod kterým si v rámci pole pamatujeme hodnotu.
Například poleCisel[1] = 23
je uložení čísla 23 na pozici "1" do pole jménem "poleCisel".
K čemu je to dobré? Najednou nepotřebujeme hromadu proměnných na to, abychom si pamatovali větší množství dat. Navíc, všechny proměnné jsou napevno
zadrátovány ve zdrojovém kódu, a není možné "programátorsky" jejich počet změnit. Pole máme jen jedno, a jeho velikost přizpůsobíme podle toho,
na jaké indexy ("do jakých hodnot") něco uložíme. Typicky se to dělá tak, že si ve druhé proměnné pamatujeme počet prvků pole. Dokud tam žádné prvky nejsou,
má proměnná hodnotu 0
. Pokud potřebujeme přidat prvek, zvýšíme proměnnou o 1 a na index, který má hodnotu této proměnné,
zapíšeme přidávaný prvek. Tímpádem nám proměnná zároveň ukazuje, jaký je nejvyšší index, kde něco najdeme.
Pole se například velmi jednoduše snoubí se smyčkou For
. Můžeme snadno projet všechny prvky jako
For i = 1
To pocetPrvku ...pole[i]...
Případně můžeme podobným způsobem pole naplnit prvky.
Indexovat nemusíme jen čísli. Dá se to dělat i textovou hodnotou. Můžeme tak vytvořit třeba pole barev, které chceme v programu na něco používat,
a indexovat je kupříkladu hodnotami ["barvaPozadi"]
,
["barvaTextu"]
, ["zvyraznovaciBarva"]
atd.
Další možnost, jak to využít, je uchovávat si v poli nějaké údaje, která souvisí. Například o uživateli, a indexovat pole hodnotami
["jmeno"]
, ["prijmeni"]
,
["heslo"]
, ["datumNarozeni"]
,
["telefon"]
, ["email"]
atd.
A poslední možnost je vyrobit tímto způsobem nějaké "mapování", kupříkladu písmena abecedy na písmena v Morseovce:
morseovka["a"] = ".-"
morseovka["b"] = "-..."
morseovka["c"] = "-.-."
a tak dále.
A pak je hodně užitečná ještě jedna věc - nemusí to zůstat jen u skříně se šuplíky. Můžeme totiž dělat tzv. vícerozměrná pole. Normální pole, o kterém jsme mluvili doteď, je "jednorozměrné", má jedny hranaté závorky a je to skříň se šuplíky. Ovšem i skříň můžeme vložit do pole, a uděláme tak sklad s více skříněmi. Takové pole má hranaté závorky dvoje (prvními vyberu skříň, druhými šuplík ve skříni), takže je "dvojrozměrné". Dále jde udělat pole "trojrozměrné", to je skladiště, které má více skladů, které mají skříně, které mají šuplíky. Čtyřrozměrné pole je průmyslová zóna, která má vícero skladišť, které mají sklady, které mají skříně, které mají šuplíky. Těch rozměrů si můžeme vymyslet libovolné množství.
Jednoduše si tak můžeme vytvořit například seznam více uživatelů: (ty jména a maily jsme si vymysleli)
uzivatele["karel"]["jmeno"] = "Karel"
uzivatele["karel"]["prijmeni"] = "Novotný"
uzivatele["karel"]["email"] = "novotny.kaja@seznam.cz"
uzivatele["pepa"]["jmeno"] = "Josef"
uzivatele["pepa"]["prijmeni"] = "Král"
uzivatele["pepa"]["email"] = "kraljosef@gmail.com"
a nebo už třeba nějakého uživatele máme
eliska["jmeno"] = "Eliška"
eliska["prijmeni"] = "Spurná"
eliska["email"] = "elis.spurna@seznam.cz"
tak ho můžeme rovnou zařadit do seznamu
uzivatele["eliška"] = eliska
Další využití je, že například můžeme reprezentovat nějakou tabulku, která má řádky a sloupce, což je přirozeně dvourozměrné pole. Jednu takovou "tabulku" dobře známe, je to grafické okno. To je v podstatě (můžete si ho tak představit) dvourozměrné pole, indexované pozicemi x a y, obsahující barvy pro jednotlivé pixely. Pokud bychom třeba dělali nějakou hru s bludištěm, také bychom si bludiště ukládali do takové dvourozměrné tabulky.
Řídicí struktury nám narušují to, co jinak platí - že kód se čte řádek po řádku a vykonává se přesně v pořadí, jak je napsán. Je to také to, co nám odlišuje kalkulačku od počítače - Kalkulačka jen počítá, jak ji přikazujeme. Počítač je mocnější, někdy se může rozhodnout vykonat nějaký kus kódu mimo hlavní pořadí.
Struktura tedy vždy obaluje nějaký kus kódu (několik "výkonných" řádků), a ten se pak vykoná podle toho, jak to daná struktura určí. Říkáme tak, že struktura "obsahuje" nějaký kód, a jeho vykonání se řídí strukturou, ve které je obsažen. Proto jsou ty struktury "řídicí" - řídí nám tok programu z hlediska kódu, který obsahují.
Každá struktura má tedy svůj začátek a konec. Začátek nám značí "otevírací klíčové slovo", což je název struktury. Konec je značen "zavíracím klíčovým slovem", což je "End" plus název struktury.
Mezi řádky s těmito klíčovými slovy pak píšeme samotný kód, který struktura obsahuje. Je vhodné oddělit tento kód mezerami od levého okraje, aby byl opticky skřípnut mezi klíčovými slovy, a bylo tak na první pohled viditelné členění našeho kódu.
-> napíše se pomocí klíčových slov If ... Then
a EndIf
Rozděluje kód na část, která se vykoná jen, když platí nějaká podmínka.
Podmínku vytvoříme tak, že porovnáme proměnnou a hodnotu nebo dvě proměnné. (Nebo dvě hodnoty, ale to není moc užitečné)
Porovnávat můžeme pomocí těchto operátorů:
=
rovná se - platí, když jsou srovnávané věci stejné<
menší než - platí, když je levá věc menší, než pravá>
větší než - platí, když je levá věc větší, než pravá<=
menší rovno - platí, když je levá věc menší, než pravá, nebo stejná>=
větší rovno - platí, když je levá věc větší, než pravá, nebo stejná<>
nerovná se - platí, když jsou srovnávané věci různéEndIf
. Za podmínkou musí následovat Then
!
Pokud chceme přidat kód, který se vykoná, když podmínka neplatí, tak ho oddělíme pomocí Else
.
Pokud chceme udělat "kaskádu" více podmínek za sebou, na vnořené podmínky použijeme ElseIf
.
Pokud potřebujeme zapsat podminek více, pak každou podmínku dáme do závorek ()
a pospojujeme je
pomocí And
("a zároveň"), pokud mají platit současně, nebo pomocí
Or
("nebo"), pokud stačí, aby platila jedna z nich.
Podmínky jsou hezky vidět v příkladu s kalkulačkou.
-> napíše se pomocí klíčových slov While ...
a EndWhile
Rozděluje kód na část, která se opakuje, dokud platí nějaká podmínka. Vždy, než se začne kód ve smyčce vykonávat,
se podmínka znovu ověří. Pokud platí, kód se vykoná. Pokud neplatí, pak říkáme, že smyčka skončí a program pokračuje
s kódem za smyčkou - za EndWhile
. Podmínky jsou stejné, jako u řídicí struktury If
, viz výše.
(Tedy se jen podmínka neověří jednou před vstupem, ale bude se ověřovat opakovaně na začátku každé iterace, dokud bude platit)
Smyčku používáme, když nevíme, kolikrát se nám bude opakovat. Například, když očekáváme nějaký vstup od uživatele - třeba heslo nebo dáváme uživateli na výběr - třeba možnosti 1 - 5. Pokud uživatel napíše správné heslo nebo číslo od 1 do 5, smyčka končí a pokračujeme dál. Pokud ale uživatel napíše špatné heslo nebo nějaké jiné číslo, než 1 - 5, zeptáme se ho smyčkou znovu. A znovu. A znovu - smyčka prostě poběží, dokud bude platit podmínka, že uživatel nezadal očekávaný vstup.
Pokud se dostaneme do bodu, že jen program neustále něco opakuje, a to po něm chceme, dokud si ho uživatel nezavře křížkem
(například chceme do nekonečna přehrávat animaci), můžeme pomocí smyčky While
vytvořit
tzv. "nekonečnou smyčku" - podmínka v záhlaví jednodušše vždy bude platit. Kvůli přehlednosti se však využívá trik, že do záhlaví
napíšeme jen textovou hodnotu "True"
, čili anglicky pravda. Small Basic bere textový řetězec se slovem "True"
jako splněnou podmínku.
Nekonečný cyklus je hezky vidět v příkladu s animací mraků.
-> napíše se pomocí klíčových slov For ... To ...
a EndFor
Rozděluje kód na část, která se zopakuje přesně několikrát. Smyčce se dá nějaká proměnná a limit. Program pak po každém proběhnutí
smyčky přičte jedničku, a pokud se proměnná do limitu vejde, proběhne znovu. Až v proměnné skončí větší číslo, než je limit,
pokračuje program s kódem za smyčkou - za EndFor
.
Základní forma smyčky vypadá například takto:
For i = 1 To 10 ... EndForA ta se nám vykoná desetkrát. V proměnné
i
se postupně vystřídají čísla 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. Je možné
také (nepovinně) zadat velikost kroku pomocí Step
. Pak je možné například projet smyčku jen pětkrát a v proměnné vystřídat
čísla lichá (1, 3, 5, 7, 9):
For i = 1 To 10 Step 2 ... EndForNebo změnit smyčku na "odpočítání" pomocí záporného kroku. Smyčka pak projede v proměnné
i
čísla 10, 9, 8, 7, 6, 5, 4, 3, 2, 1:
For i = 10 To 1 Step -1 ... EndFor
Smyčku používáme, když víme, kolikrát se nám bude opakovat. Příklad je, že se uživatele zeptáme na to, kolikrát se má něco zopakovat, pak nám limit udává proměnná, a nebo to prostě víme, pak je to pevně dané číslo. Smyčky se snadno kombinují, jak je vidět na příkladu s vypsáním malé násobilky, jen pozor, ať si zvolíte různé řídicí proměnné!
-> napíše se pomocí klíčových slov Sub
a EndSub
Rozděluje kód. Část, která je uzavřena mezi klíčovými slovy, je kód podprogramu, tedy kód naší subrutiny.
Veškerý kód se při čtení programu jen zapamatuje, jako že je to kód pojmenovaného podprogramu, ale nevykoná se.
Subrutina může být zapsána kdekoli v programu, jen nesmíme dávat subrutinu dovnitř jiné subrutiny, podmínek ani smyček.
(Tedy jako struktura stojí samostatně, je to prostě kus kódu mimo hlavní kód.)
Kód uvnitř subrutiny se vykoná vždy, když subrutinu zavoláme. Volání se provádí stejně, jako volání funkcí na objektech. Uvedeme název subrutiny a kulaté závorky.
Ty budou vždy prázdné, neboť našim subrutinám nepodstrkujeme žádná data, vše si přečtou z proměnných.
Tomu se v programování říká, že máme "globální prostor proměnných" - na všechny proměnné vidíme odkudkoli z programu. To je někdy výhodné,
a jindy nevýhodné, jak uvidíme. Většinou se nám to ale hodí právě k tomu, abychom nějaké subrutině připravili data - buďto v jiné subrutině,
nebo přímo v hlavním kódu. Díky sdíleným proměnným si je pak subrutina snadno přečte.
Zde tedy příklad subrutiny:
TextWindow.WriteLine("Začátek programu")
'zavedení subrutiny jménem "Podprogram1"
Sub Podprogram1
TextWindow.WriteLine("Výpis z podprogramu 1")
EndSub
TextWindow.WriteLine("Prostředek programu")
Podprogram1() 'Zavoláme subrutinu
TextWindow.WriteLine("Konec programu")
Tento program postupně vypíše: Začátek programu - Prostředek programu - Výpis z podprogramu 1 - Konec programu
.
Názvy subrutin nám editor vykresluje černě, podobně, jako třeba proměnné. Při jejich volání nesmíme zapomenout na závorky.
Pro připomenutí, že subrutinu "voláme" je v nápovědním panelu označena symbolem telefonu.
Domluvili jsme se, že pro větší přehlednost budeme dávat subrutinám jména, která začínají na VELKÉ písmeno. Jméno subrutiny by mělo mít formu
rozkazu, aby se kód dobře četl. Dobrá jména jsou tedy Vykresli(), PripravPromenne(), ZabijHrace(), RestartujHru()
a tak podobně. Název "Vykreslit" je ještě únosný, "Vykresleni" je již špatně. Háček je v tom, že ve zdrojovém kódu, při zavolání subrutiny,
uvidíme pouze řádek Vykresleni()
, a to je divné - programu sice dáváme rozkaz
k vykreslení, ale s tímto pojmenováním to děláme nikoli tak, že mu řekneme (napíšeme) "vykresli", ale tak, že mu řekneme "vykreslení",
a to nedává moc smysl, takže se kód hůře čte.
Subrutiny se nám hodí na dvě věci - tou nejzásadnější je rozdělení kódu na logické kusy, které jen zavoláme. Když máme kód delší, špatně se v něm orientuje. Jeho rozdělením na menší úseky, které dáme do subrutin, ho zpřehledníme. Za druhé také snadno oddělíme kusy kódu, které používáme často. Kdykoliv takový kus potřebujeme vykonat, jednoduše zavoláme příslušnou subrutinu, a nemusíme kód kopírovat z místa na místo. Navíc, pokud potřebujeme kód upravit, uděláme to pouze jednou přímo v subrutině, a ne na 10 místech v programu. Šetří to čas i chyby, které uděláme, když někde zapomeneme změnu provést.
Druhé použití souvidí s tím znovupoužitelným kódem. Subrutiny se používají k obsluze událostí v aplikaci.
Poslední věcí, kterou některé objekty umí, jsou takzvané události. Jedná se o zvláštní typ vlastnosti na objektu, v nápovědě má ikonku zeleného kroužku s bleskem.
A ta ikonka dobře ilustruje, co to taková událost je. Když totiž někde uhodí blesk, náhodně se to stalo. Byla to náhodná událost.
K něčemu podobnému pak může dojít i v našem programu. Nestane se to, že v kódu dojdeme na nějaké místo, a to se v ten moment prostě vykoná.
Stane se to, že zásahem nějaké vyšší moci k něčemu dojde v předem neznámý čas, a náš program na to nějak odpoví.
Taková vyšší moc je typicky uživatel. Například, že uživatel pohne myší, klikne na nějaké její tlačítko nebo stiskne klávesu na klávesnici. Nevíme sice předem, kdy to udělá, ale pokud se tak stane, chceme na to umět zareagovat. A přesně k takovýmhle věcem (a jim podobným) události slouží.
Ve skutečnosti je to jednodušší, než by se zdálo. Událost je, dle textu výše, jen zvláštní typ vlastnosti objektu. Do této vlastnosti se dá přiřadit název subrutiny. Tomu se říká obsluha události. Chceme-li v programu reagovat na nějakou událost, napíšeme pro ni "obslužný kód", "obsluhu". A tento kód se nám pak zavolá, když na událost dojde.
A kde se tedy nějaká událost vezme? Má ji na sobě objekt, jako tu speciální vlastnost, například na objektu GraphicsWindow
událost MouseMove
. Ta nám reprezentuje událost "Uživatel pohnul nad grafickým oknem myší". Pokud se tak opravdu stane,
Objekt to sám pozná a pokud má nějakou obslužnou subrutinu k události přiřazenou, sám od sebe nám ji zavolá, nezávisle na zbytku programu.
Události se tedy berou na objektech, které samy poznají, že událost nastala, a samy zavolají obsluhu. Na nás je jen příslušnou obsluhu naprogramovat. Vytvoříme si tak kupříkladu
Sub ZpracujPohybMysi ... EndSub
a pak někde zavoláme GraphicsWindow.MouseMove = ZpracujPohybMysi
.
Všimněte si dobře, že tam nejsou žádné závorky. Subrutinu nevoláme, jen její jméno dáváme do události, která si ji bude volat sama.
S událostmi souvisí pojem konkurence. Pokud jsou nějaké dvě (a i více) věcí v konkurenci, znamená to, že se přetahují o nějaký sdílený zdroj. V reálném světě se s pojmem konkurence setkáme hlavně u různých obchodů a společností, které se přetahují o zákazníky. To je mimochodem pro trh dobré. V programování to ale moc dobré není. Konkurence nastává, pokud se nějaké dva souběžně běžící kusy kódu pokoušejí dělat nějakou podobnou činnost, ke které potřebují sdílený zdroj, například objekt typu želva, nebo nějakou proměnnou. Pokud si jeden kód do proměnné uloží nějakou hodnotu, ale druhý kód mu ji přemaže svou hodnotou dříve, než si první kód její obsah zase přečte, první kód se tím rozbije. Stejně, jako když dá první kód Želvě nějaký kreslicí pokyn, ale než ho Želva dokončí, přijde ji jiný pokyn od druhého kódu. Typicky se správně nedokončí ani jeden, a my jako programátoři nemáme vzhledem k povaze souběžně běžících kódů šanci jakkoli vytušit, jak taková situace dopadne, a není tak možné na její řešení napsat kód.
Jak je ale vůbec možné, aby se vykonávaly dva kódy souběžně? V reálném programování se to může stát mnoha způsoby, a je to důležitá schopnost, proto je studium konkurence tak důležité. Ve Small Basicu nám ale běží jen jeden kód. Ovšem, jak už jsme psali, konkurence tu souvisí s událostmi. Ty totiž nastávají ve zcela náhodné okamžiky, a tak na ně nemůžeme reagovat hlavním kódem. Namísto toho se při každém nastání události vytvoří samostatně běžící kód, který vykoná obslužnou subrutinu. A to i když událost nastane víckrát po sobě - každé nastání vyvolá vznik vlastního nezávislého kódu s naší subrutinou, a jednotlivá souběžně běžící vykonání si nesmí konkurovat.
Takže co musíme udělat je zařídit, že obslužná subrutina nedostane šanci "vlézt do zelí" hlavnímu kódu či jinému volání téže subrutiny. Buďto máme v obsluze akci, která je krátká, že se vykoná prakticky okamžitě, a tak se nestane, že by je uživatel stihnul vyvolat přes sebe. Nebo je akce sice dlouhá, ale nepoužívá ke svému běhu žádnou společnou věc (proměnnou nebo objekt "jedináček" typu Želva). V těchto případech je možné napsat kód akce přímo do obslužné subrutiny a nic se nebude dít (viz třeba příklad s Malováním nebo jednoduchou hrou).
Pokud ale máme akci, jejíž vykonání bude nějakou chvíli trvat, a akce třeba i jen čte A ZAPISUJE nějaké proměnné, musí běžet pouze jedna naráz. Kód této akce tedy nemůžeme napsat přímo do obslužné subrutiny, ale musíme ji vykonat hlavním kódem, kterému dá subrutina pouze pokyn, že to má udělat. To je řešení konkurence - nebude si tu konkurovat samotná akce, ale pouze pokyn na její vykonání. Hlavní kód pak bude poslouchat jediný pokyn najednou. Jedním ze způsobů, jak takovou komunikaci udělat, je pomocí konceptu "herní smyčka", který je popsán níže.
Koncept herní smyčky se týká aplikací v grafickém okně. Pokud máme nějakou déle trvající funkcionalitu (akci), kterou aktivujeme nezávisle na hlavním kódu (typicky myšovou či klávesnicovou událostí), nemůžeme ji naprogramovat přímo do obsluhy aktivační události. To je z následujícího důvodu - uživatel provede událost, a nezávisle na hlavním kódu se začne provádět. Nyní, pokud uživatel opět provede aktivační událost, začne se obsluha opět provádět, opět nezávisle na hlavním kódu, a také nezávisle na druhé obsluze, která ještě dobíhá. Pokud obsluha používá nějakou funkcionalitu, kterou potřebuje mít pro dobu provedení akce pro sebe (Želvu či jiný objekt, obsah proměnné, geometrický útvar apod.), budou se o ni s později zavolanou obsluhou "prát" a ani jedna zřejmě neproběhne korektně.
A my jako programátoři nemáme jak vědět, jak to doběhne, pakliže nezajistíme, že obsluha akce bude běžet jen jedna najednou.
To zajistit není až tak jednoduché, ale můžeme to udělat pomocí právě té "herní smyčky". Veškeré události necháme na hlavním
kódu, a obsluha událostí jen zapíše do zvláštní proměnné pokyn, že uživatel chce něco provést. Jakmile akce v rámci hlavního
kódu doběhne, zapíše hlavní kód do té proměnné, že se nic nemá dělat. To celé zabalíme do nekonečné smyčky
(While "True"
), která se bude jen tak naprázdno točit, dokud
se v pokynové proměnné neukáže pokyn k akci. Pokud se z proměnné přečte pokyn, že se má provést akce, smyčka akci zavolá
(či rovnou vykoná), během ní je smyčka pořád v té iteraci (průběhu cyklu), která přečetla pokyn. Jakmile akce doběhne,
zapíše se opět pokyn "nic nedělej" a smyčka se opět může točit na prázdno.
To je teorie, konkrétní příklad je vidět v příkladovém zdrojovém kódu.
Objekt TextWindow
představuje jednoduché textové okno, do kterého můžeme psát po řádkách text a číst, co napíše uživatel na klávesnici.
Vypsání textu na okno se provede příkazem Write("text na výpis")
Pokud navíc chceme odřádkovat, příkaz je WriteLine("text na výpis s odřádkováním")
Čtení textu, co napsal uživatel, se udělá příkazem Read()
, který vrací uživatelův text.
Uložení textu do proměnné text
vypadá tedy text = TextWindow.Read()
Pokud chceme, aby uživatel napsal číslo, použijeme příkaz ReadNumber()
, a uživatel nebude moc napsat nic jiného,
nežli číslice (a mínus kvůli záporným číslům, a tečku kvůli desetinným číslům).
Někdy se hodí okno vyčistit, "vygumovat, smazat tabuli". To samozřejmě nevymaže proměnné, jen nám zmizí veškerý doposud napsaný text,
a to jak ten, co napsal náš kód, tak ten, co naklapal uživatel. Udělá se to příkazem Clear()
.
Pauzu vyvoláme příkazem Pause()
, vypíše se hláška "Press any key to continue..." a čeká se na
stisk klávesy uživatelem.
Pokud nechceme vypsat anglickou hlášku, použijeme příkaz PauseWithoutMessage()
.
Objekt GraphicsWindow
představuje grafické plátno, jaké známe třeba z Malování, a umožňuje nám kreslit na něj.
Okno je samo o sobě jen "prázdné plátno", nejrůznější obrázky apod. do něj dostaneme přes objekty
Turtle
, Shapes
& Controls
.
Ty nám umožňují kreslit želví grafiku, vkládat geometrické tvary a texty & vkládat a ovládat textová pole a tlačítka.
Okno má několik důležitých vlastností, jež nastavují, jak je okno velké, co s ním uživatel smí dělat, jaké barvy budou použité apod.
Kromě nastavování speciálních vlastností umí okno také zpracovávat klikání na myš a do klávesnice uživatelem, ve formě událostí.
A v neposlední řadě také vykreslovat tvary a texty, podobně, jako objekt Shapes
, rozdíl viz níže.
Grafické okno se skládá z jednotlivých "barevných bodů", neboli "pixelů", což jsou malé barevné čtverečky, které nám tvoří obrazovku počítače, a tak i samotné grafické okno. Jsou pěkně vedle sebe, jako čtverečky na kostičkovaném papíře, na kterém se třeba hrají piškvorky, lodě a podobné hry.
Každý pixel má svoje "souřadnice", to jsou dvě čísla, která udávají, kde pixel v rámci okna je. Značí se obvykle (x; y), například by se pixel mohl nacházet na
souřadnicích (2; 15), tedy "souřadnice dva, patnáct".
První číslo, "x" neboli "x-ová souřadnice", nám udává pozici na řádku, pozici zleva doprava, v kolikátém sloupečku se pixel nachází (jako zeměpisná délka na mapě).
Druhé číslo, "y" neboli "y-ová souřadnice", nám udává pozici ve sloupečku, pozici shora dolů, v kolikátém řádku se pixel nachází (jako zeměpisná šířka na mapě).
Vzhledem k tomu, že souřadnice rostou doprava a dolů, je zřejmé, že pixel v levém horním rohu má souřadnice (0; 0), pixel v pravém dolním rohu pak
(šířka_grafického_okna - 1; výška_grafického_okna - 1). Například pro okno o velikosti 800x600 pixelů je vpravo dole pixel se souřadnicemi (799; 599).
Důležité upozornění - věci v grafickém okně mohou získat i takové souřadnice, které jsou větší, než ten pravý dolní roh. V takové případě je uživatel samozřejmě nevidí, protože jsou mimo hranice okna. Důležité ale je, že pořád tam jsou, takže když je posuneme zpátky, nebo si uživatel okno do těch míst roztáhne, opět objekt uvidí.
Šířku a výšku okna nastavíme pomocí vlastností Width
a Height
. Udáme číslo, a na takový počet
pixelů se nám okno roztáhne.
Vlastnosti Left
a Top
nám udávají, jak je okno vzdáleno od levého a horního okraje monitoru.
Pokud nechceme, aby uživatel oknu mohl změnit rozměr (roztáhl nebo stáhl), použijeme vlastnost CanResize
. Do té dáváme dvě
textové hodnoty - "True"
jako pravda a "False"
jako nepravda.
Pravda je výchozí a uživatel okno roztáhnout dokáže. Nepravda značí, že to nedokáže.
Vlastností Title
nastavíme "titulek okna", tedy jakýsi název programu, který je napsán na horní liště grafického okna a je vidět
i v systémové liště se spuštěným oknem.
V Grafickém okně jsou celkem tři vlastnosti na nastavení barev. Barva se nastavuje jako textová hodnota. Tato hodnota je buďto něco jako "#5689A5"
,
tedy znak křížek, následování šesti číslicemi či písmeny A až F. Tento způsob zápisu je složitější, zájemci se mohou podívat níže do doplňujících poznatků.
Úplně v pohodě si totiž vystačíme s barvami, které nám autoři jazyka pojmenovali. Jejich přehled včetně českého překladu najdete zde. Jako hodnotu
dané vlastnosti musíte uvést anglický název z prvního sloupce tabulky, například "OliveGreen"
.
Vlastnost BackgroundColor
nám udává, jakou barvu bude mít pozadí grafického okna.
Vlastnost PenColor
nám udává, jakou barvu bude mít pero.
Vlastnost BrushColor
nám udává, jakou barvu bude mít štětec.
S perem souvisí ještě vlastnost PenWidth
, ta je číselná, a udává nám šířku pera.
Pero a štětec (brush a pen) nám řídí vykreslování v grafickém okně. Těchto vlastností využívá jak samotné grafické okno, tak i objekty
Turtle
, Shapes
a Controls
, které nám na okno
také umí vykreslovat. Vykreslování přímo oknem je popsáno níže, základní poznatky o tom se pak uplatní i u zmíněných vykreslovacích objektů.
Základní příkazy jsou stejné, jako u textového okna.
Okno se nám objeví, jakmile s ním v kódu poprvé uděláme nějaký úkon, kupříkladu nastavení velikosti. Ukázání okna můžeme vždy vyvolat příkazem
Show()
, skryjeme jej pomocí Hide()
.
Grafické okno "vyčistíme" pomocí funkce Clear()
. Funkce vymaže všechny čáry nakreslené želvou i želvu samotnou,
tvary přidané objektem Shapes
, ovládací prvky přidané objektem Controls
a přemaže všechny vykreslené tvary barvou pozadí.
Pomocí funkce ShowMessage(zpráva, titulek)
můžeme
zobrazit vyskakující okno s informační zprávou. Zprávu předáme jako první parametr, jako druhý parametr dáme titulek,
který se zobrazí v liště okna se zprávou. Dokud uživatel okénko se zprávou neodklikne, nebude moci nijak pracovat s hlavním oknem,
a kód zůstane pozastavený na příkaze ShowMessage(...)
.
Grafické okno má i pomocné funkce pro práci s barvou. Zjevně by bylo zbytečné přidávat nějaký objekt "Color", ve kterém by se nacházely -
už proto, že barvu vyjádříme textovou hodnotou s názvem barvy nebo šestimístným kódem. Jedná se zejména o příkazGetRandomColor()
,
který nám vrátí náhodnou barvu. To se může hodit, když nevíme, jakou barvu chceme něčemu dát - vybereme ji zkrátka náhodně.
Ještě je nám k dispozici příkaz na míchání barev z RGB složek -
GetColorFromRGB(červená, zelená, modrá)
,
jehož popis a vysvětlení toho, co vlastně dělá, najdou dobrovolní zájemci dole v doplňujících poznatcích o barvách.
Na grafickém okně jsou události pro reagování na uživatelovo zacházení s myší a klávesnicí.
Pokud uživatel pohne myší, nastane událost MouseMove
. V rámci obsluhy této události tak můžeme
reagovat na to, kde se právě myš nachází, či jaká jsou stisknuta tlačítka. Pozici myši získáme v 99% případů přímo od grafického okna.
Grafické okno má totiž na sobě vlastnosti MouseX
a MouseY
, podobně,
jako samotná myš. Tyto se ale vztahují přímo k oknu samotnému, a ne k monitoru, takže nezáleží, kde uživatel okno má.
Ještě si uvědomme, že stav tlačítek nám během obsluhy hýbání myší neříká nic o tom, kdy bylo tlačítko stisknuto. Pouze víme,
či jej uživatel drží či ne, a tak můžeme předpokládat, že bylo drženo/puštěno stejným způsobem, jako při začátku pohybu,
který obsluhujeme.
Pokud chceme vědět, kde se myš nacházela naposledy, musíme si to vždy na konci obslužné subrutiny zapamatovat. Tj. na konci subrutiny
zapíšeme do vyhrazených proměných aktuální pozici. Na začátku takové subrutiny pak máme poslední známou pozici
v proměnných z minula uloženou, a můžeme tak spočítat přímku, po které uživatel myší pohnul. Úplně na začátku programu pak
těsně před přiřazením obslužné subrutiny do proměnných uložíme současnou polohu myši,
s ní uživatel totiž začíná.
lastMouseX = GraphicsWindow.MouseX
lastMouseY = GraphicsWindow.MouseY
GraphicsWindow.MouseMove = HandleMouseMove
Sub HandleMouseMove
'Zde můžeme použít proměnné lastMouseX a lastMouseY
'...
lastMouseX = GraphicsWindow.MouseX
lastMouseY = GraphicsWindow.MouseY
EndSub
Pokud uživatel používá tlačítka myši, nastane událost MouseDown
při zmáčknutí tlačítka,
a MouseUp
při puštění tlačítka. Tyto události obsluhují přesně moment, kdy uživatel změnil
stav některého tlačítka - takže aktuální stav vlastností myši, které sdělují stisknutost tlačítek, jsou aktuální vůči právě
obsluhované události. Pokud si v proměnné pamatujeme stav některého tlačítka, a aktuální stav je opačný, je jasné, že došlo ke změně.
Nesmíme ale zapomenout obsluhovat obě události a proměnnou udržovat aktuální, jinak program zřejmě začne dělat nesmysly!
Přímo skrze objekt grafického okna do něj můžeme vykreslovat. Základní příkaz je SetPixel(x,
y, barva)
, který nám pixel na zadaných souřadnicích (x, y) obarví zadanou barvou.
Pokud chceme zjistit, jakou barvu má nějaký pixel, použijeme příkaz GetPixel(x,
y)
, který nám barvu vrátí ve formě šestimístného kódu. Pozor, to nefunguje, když máme souřadnici překrytou
útvarem přidaným přes objekt Shapes
! Více viz popis objektu Shapes
.
Příkaz GetPixel()
si taktéž nevšímá barvy pozadí! Pokud na daný pixel nenakreslíme nic, vrací příkaz vždy
"#000000"
, tedy černou, bez ohledu na barvu pozadí!
Asi uznáte, že nastavovat pixel po pixelu může být užitečné, například se tak dají kreslit zajímavé útvary smyčkami, ale pokud chceme vyrábět
složitější obrázky, bylo by to dost těžké. Za tímto účelem máme na grafickém okně několik příkazů "Draw" a několik příkazů "Fill".
Příkazy začínající slovem "Fill" (vyplnit) nám "vyplní" geometrický útvar na plátno podle specifikovaných požadavků (pozice, tvar, velikost). Útvar
bude kompletně vybarvený barvou štětce. "Štětec" grafického okna tedy slouží k vybarvování útvarů, k vyplňování barevných ploch.
Příkazy začínající slovem "Draw" (nakreslit) nám obkreslí geometrický útvar na plátno podle specifikovaných požadavků. Útvar bude mít nakreslený pouze
svůj obvod, či obrys, a to barvou pera, a tlustý bude podle toušťky pera. "Pero" grafického okna tedy slouží ke kreslení čar, kreslení tahů.
POZOR - Existují i další kreslicí příkazy, které také začínají slovem "Draw". Jedna taková dvojice se používá ke psaní textů na okno. Ale
je tam jedna zrada, text se vypisuje barvou štětce, nikoli pera! Bohužel název je matoucí. Více dále v textu.
Druhá dvojice slouží pro vykreslování obrázků typu fotky apod. Vyžaduje to spolupráci s dalšími objekty, takže je to celé popsáno níže
spolu s objektem ImageList
.
Postupné volání příkazů do okna vždy dokresluje. Tudíž záleží na pořadí příkazů, ve kterém je vykonáte. Různé pořadí vede k různému překrytí
útvarů a tudíž rozdílným výsledkům! Pokud tedy chceme nakreslit nějaký tvar i s okrajem, voláme nejprve "Fill" příkaz, který plochu tvarů
vyplní, a až po té voláme "Draw", který namaluje okraj. Okraj totiž má tloušťku dle tloušťky pera, čehož si "Fill" pochopitelně nebude všímat,
protože "Fill" kreslí štětcem.
Pokud zavoláme nejprve "Draw" a pak až "Fill" se stejnými parametry, výsledný tvar bude mít vždy obrys o tloušťce 1. Je tomu tak proto,
že "Fill" příkazy nedotahují tvary úplně mezi zadané souřadnice, ale jen "k nim", tudíž po obvodu zbyde vždy okraj s jednotkovou šířkou.
(Pokud tedy zadám "Fill" příkazu čtverec ze souřadnic (10, 10) na souřadnice (50, 50), pokryjí se pouze pixely mezi souřadnicemi (11, 11)
až (49, 49) - to je to dotažení "k souřadnicím" - pokryjí se pixely se souřadnicemi > většími, než (10, 10) a zároveň < menšími, než (50, 50).
Naopak "Draw" příkaz pokryje i zadané souřadnice, čili okraj vykreslí přes souřadnice, které jsou >= větší nebo rovné (10, 10) a zároveň
<= menší nebo rovné (50,50) - a proto tedy "prosvítá" ten jednotkový okraj. Více je vidět na konci příkladu "14 Tvary".)
Základními tvary pro kreslení jsou čára, obdélník, elipsa, trojúhelník a text. Vykreslovat lze také obrázky, je to popsáno u objektu
ImageList
, jelikož to vyžaduje spolupráci s ním.
Čáru nakreslíme (perem) pomocí příkazu
DrawLine(x-start, y-start,
x-cíl, y-cíl)
. Příkaz dostane dvě dvojice souřadnic (x, y),
startovní a cílové, a natáhne mezi nimi čáru.
Obdélník kreslíme příkazem DrawRectangle(x-start, y-start,
šířka, výška)
a komplementárním
FillRectangle(x, y,
šířka, výška)
. Příkaz dostane dvojici souřadnic (x, y),
které představují levý horní roh obdélníka (tedy ten s nejnižšími souřadnicemi) a šířku a výšku. Obdélník pak vzniká od x-ové souřadnice
doprava o zadanou šířku, a od y-ové souřadnice dolů o zadanou výšku.
Čtverec nakreslíme příkazem pro obdélník, se shodnou šířkou a výškou.
Elipsu kreslíme příkazem DrawEllipse(x-start, y-start,
šířka, výška)
a komplementárním
FillEllipse(x, y,
šířka, výška)
vyplníme "elipsoid". Příkaz dostane dvojici souřadnic (x, y),
které představují levý horní roh pomyslného obdélníka, který se dá nakreslit kolem elipsy, a šířku a výšku. Elipsa má dvě tzv. "osy",
hlavní (delší) a vedlejší (kratší). Jsou to jakési "dva průměry" (kružnice má jen jeden), které ji tvoří - a to ji odlišuje od kružnice.
Tyto osy si ale můžeme představit i mimo střed elipsy podél jejích okrajů, a pak nám vlastně tvoří obdélník, který elipsu uzavírá.
Proto má příkaz stejnou podobu jako obdélník. Funguje to stejně, jako když vytváříte elipsu v programu "Malování", a vidíte tam i
obdélník, co elipsu uzavírá, než ji odkliknete. Toto je úplně stejné.
Kružnici (a "Fill"nutý Kruh) nakreslíme příkazem pro elipsu, se shodnou šířkou a výškou, odpovídající průměru kružnice.
Trojúhelník kreslíme příkazem DrawTriangle(x1, y1,
x2, y2, x3, y3)
a komplementárním FillTriangle(x1, y1,
x2, y2, x3, y3)
.
Příkaz dostane tři dvojice souřadnic (x, y), které představují všechny tři rohy výsledného trojúhelníka. Příkaz má sice rekordní počet parametrů,
celých šest, ale jinak je takto přímočarý. Jen si dávejte pozor, ať se v souřadnicích neztratíte.
Dále je možné vykreslovat text. Budeme si teprve ukazovat.
Objekt Turtle
představuje Želvičku, používanou ke kreslení tzv. želví grafiky. Tu si lze snadno představit jako když se kreslí postupným tahem pera.
Tedy psaní psacím (i tiskacím) písmem, kreslení domečku jedním tahem, kreslení útvarů typu spirála atp. Jednotlivé jednoduché pohyby na sebe navazují a tvoří celek.
Želva má "ocásek", který umí zvednout a dát dolů. Pokud jej má dole (výchozí stav), a hýbe se, nechává za sebou čáru. Pokud ho má nahoře, pohybuje se
bez kreslení. Ocásek nám představuje pero grafického okna. Čára kreslená želvou má tedy šířku a barvu dle vlastností pera objektu GraphicsWindow
.
Ocásek zvedneme funkcí PenUp()
, dolů ho dáme funkcí PenDown()
Želvu můžeme posílat na body v grafickém okně pomocí příkazu
MoveTo(souřadnice x, souřadnice y)
.
Rychlost želvy nastavujeme vlastnosti Speed
. To je číslo od 1 do 10, 1 - 9 jsou různé rychlosti, při 10 se želva teleportuje.
Upozorňujeme, že čáry nemusí jít úplně rovně, přestože se mění jen jedna souřadnice. Je to vidět na příkladu s domečkem jedním tahem, kdy želva tahy zcela nenaváže.
To je bohužel normální, a je to způsobeno směrováním želvy a následným otáčením. Následující způsob, který je vidět na druhém příkladu se stejným domečkem,
tuto chybu nemá, ale na kreslení předem přesně známých tvarů není tak pohodlný.
Želvě se dá totiž také říct jen "pohni se rovně" o zadanou vzdálenost a želva ji urazí, ve směru, do kterého je
natočena - slouží na to funkce Move(vzdálenost)
.
Natočení želvy pak udáváme pomocí úhlů ve stupních, od
0
do 359
. Dělá se to vlastností Angle
.
Úhel 0 je, když želva kouká nahoru. 90 je doprava, 180 dolů a 270 doleva. Je možné použít i záporná čísla, proti směru hodinových ručiček, kdy -90 je doleva, -180 dolů a -270 doprava.
Pokud chceme želvu otočit o daný úhel (tedy jen víme velikost pootočení), použijeme příkaz Turn(úhel)
. 90 otočí želvu kolmo vpravo,
-90 kolmo vlevo. 180 i -180 mají stejný efekt, jen to želva vezme různých stran. Otočení o 360 nemá vliv.
Tedy nastavení vlastnosti Angle
je "absolutní" - volání
Turtle.Angle = 90
nám želvu pokaždé nasměruje přímo proti pravému okraji monitoru,
zatímco volání příkazu Turn()
je "relativní" - kód
Turtle.Turn(90)
nám želvu vždy pootočí doprava o pravý úhel (o 90°), a výsledek
tedy závisí na tom jak se koukala původně - teď kouká kolmo po směru hodinových ručiček vůči původnímu směru.
A stejně, jako grafické okno, želvu zobrazíme pomocí příkazu Show()
, a skryjeme pomocí Hide()
.
I s neviditelnou želvou můžeme kreslit, což může být někdy docela vtipné. Želvu nám zneviditelní také volání příkazu Clear()
na
grafickém okně.
Objekt Shapes
představuje geometrické tvary, které je možno vkládat do Grafického okna, hýbat s nimi,
měnit jim velikost, natočení a další vlastnosti.
Srovnáme si nyní kreslení tímto objektem s kreslením grafickým oknem. Příkazy objektu Shapes
pro
kreslení útvarů vždy začínají na "Add", tedy přidat. A to je ten zásadní rozdíl - útvar přidaný objektem Shapes
se neprokreslí na plátno grafického okna, ale pouze je nad ním "položen".
V podstatě si to lze představit tak, že příkazy pro kreslení grafického okna opravdu pomocí jakéhosi myšlenkového pera a štětce
nakreslí tvar na plátno. Naopak příkazy objektu tvarů nic nekreslí, ale pouze stvoří daný tvar, v naší představě ho vystřihnou z papíru
o správné barvě, a položí na plátno. Proto je možné tyto tvary po plátně posouvat, otáčet apod.
Malou poznámkou se ještě vrátíme k objektu GraphicsWindow
a hlavně jeho příkazu GetPixel()
.
Veškeré kreslicí příkazy ("Fill"y, "Draw"y a SetPixel) nám, jak už jsme vysvětlili, kreslí přímo na plátno. A třeba se i vzájemně překrývají,
jako když při kreslení přetáhnete už nakreslenou část. Aktuální barvu nějakého pixelu nám pak zjistí GetPixel()
.
Tím, že útvary přidané objektem Shapes
jsou položené přes plátno, překryjí nám, cokoli se na něm nachází. Když útvary ale
přesuneme jinam či je vymažeme, opět se nám malůvka na plátně zjeví, protože tam pořád je, útvar objektu tvarů to nepřemazal, jen zakryl.
Musíme si tedy uvědomit, že pokud někam jen vložíme útvar přes objekt Shapes
, a zavoláme
GraphicsWindow.GetPixel(...)
, vrátí nám barvu, která se nachází pod útvarem, a ne barvu, jakou
tam zrovna vidíme, když je to barva útvaru. Protože příkaz se podívá, jak je plátno nabarvené, čili "nakoukne" pod jakékoli tvary, které se mu tam zrovna válí.
Přidání tvaru do okna nám vrátí zvláštní hodnotu, "jméno" právě vloženého tvaru. Skrze toto jméno pak budeme s tvarem nakládat. Musíme si jej tedy
uschovat do nějaké proměnné, jinak už nebudeme moci s tvarem nic udělat! Jediný způsob, jak se zbavit tvaru, jehož jméno jsme zapomněli, je zavolat
na grafickém okně příkaz Clear()
, který vymaže i všechny tvary.
Přidání tvaru vždy vyrobí tvar, který má obrys i výplň. Barvy obrysu a výplně se vezmou z pera a štětce grafického okna. Pokud chceme přidat útvar,
který má jen obrys, ale průhledný prostředek, je třeba nastavit štětci průhlednou barvu, tedy "Transparent"
.
Přidávání tvarů tedy vykonávají příkazy "Add...", jejichž výsledek si ukládáme. Zpravidla mají jednodušší podobu, než příkazy "Draw..." a "Fill..." na
grafickém okně, jelikož nám některé útvary vloží na počátek okna (souřadnici (0, 0)). Přesunutí na cílové místo pak děláme dalším příkazem.
Základními tvary jsou čára, obdélník, elipsa, trojúhelník a text. Je možné vložit i obrázek jako útvar, je to popsáno u objektu
ImageList
, jelikož to vyžaduje spolupráci s ním. Pokud se útvary někde překrývají,
Čáru přidáme příkazem AddLine(x1, y1,
x2, y2)
. Funguje stejně, jako DrawLine(...)
na
grafickém okně, jen je samozřejmě možné s čarou nákladat jako s tvarem.
Obdélník přidáme příkazem AddRectangle(šířka, výška)
.
Příkaz vyrobí obdélník o zadané šířce a výšce (pro čtverec dáme stejné) a umístí ho do levého horního rohu.
Elipsu přidáme příkazem AddEllipse(šířka, výška)
.
Příkaz vyrobí elipsu o zadané šířce a výšce (pro kruh dáme stejné) a umístí ji do levého horního rohu. Šířka a výška nám představuje jakýsi virtuální obdélník,
do kterého je elipsa vepsaná. Podrobnější popis je u vykreslení elipsy grafickým oknem.
Trojúhelník přidáme příkazem AddTriangle(x1, y1,
x2, y2, x3, y3)
. Funguje stejně,
jako DrawTriangle a FillTriangle na grafickém okně, jen je samozřejmě trojúhelník vložen jako útvar.
Přidávání textu si ještě představíme.
Veškeré následující příkazy berou jako první parametr jméno útvaru, se kterým chceme příkaz provést. Jméno nám vrátí příkaz "Add..." při vytváření tvaru.
Příkazem Remove(jméno)
odstraníme tvar. Odstranění je trvalé, takže jméno odstraněného útvaru
už nikdy jiný útvar nedostane, a obsah proměnné tak ztratí na významu.
Příkazem HideShape(jméno)
můžeme tvar schovat. Pokud útvar přidáme a ihned schováme, je možné,
že problikne. Pokud tvar schováme, pořád je na grafickém okně přidaný, a můžeme s ním hýbat a dělat všechny další operace dle libosti (jsou popsány níže).
Není to tedy jako u Remove(...)
, kdy tvar trvale odstraníme a již neexistuje. Jakmile budeme chtít tvar znovu ukázat,
použijeme příkaz ShowShape(jméno)
, a ten nám ho znovu zjeví.
Příkazem Move(jméno, x, y)
přesuneme tvar na nové místo, levý horní roh cílového místa předáme příkazu jako parametry x a y. Přesouváním po malých vzdálenostech můžeme vytvořit
jakousi animaci, kterou si počítáme ručně ve smyčce. Výhodou je, ža takto můžeme animovat hodně různých věcí naráz, nevýhodou je složitější výpočet.
Proto existuje ještě příkaz Animate(jméno, x,
y, čas)
, který dělá to samé, co Move(...)
, ale
tvar nám nepřesune skokem, nýbrž plynule jako animaci, která bude trvat podle čtvrtého parametru čas. Ten se udává v milisekundách, jako je tomu
u příkazu Program.Delay(...)
. Milisekunda je číslo 1000x větší, než je sekunda.
Animaci, která má trvat jeden a půl vteřiny, tedy uděláme pomocí času 1500
. Na doběhnutí animace příkaz nečeká, takže pokud
si chceme udělat více animací naráz, napíšeme prostě všechny příkazy Animate(...)
za sebe, a animace proběhnou všechny najednou.
Pokud bychom chtěli na doběhnutí počkat, musíme doplnit animaci příkazem Program.Delay(...)
,
kterému dáme stejný čas, jako animaci. Pokud mu dáme kratší čas, program bude pokračovat klidně "v půlce" animace, a můžeme tak navázat několik animací
se vzájemným zpožděním.
Příkazem Rotate(jméno, úhel)
natočíme tvar o daný úhel.
Podrobný popis úhlů je u objektu Turtle
, tady se to chová stejně. Kladný úhel otočí útvar doprava (po směru hodin)
o zadaný úhel, Záporný úhel (s mínusem) otočí útvar doleva (proti směru hodin) o tento úhel. 90 znamená otočení přímo na stranu (o pravý úhel) atd.
Podívejte se k popisu želvy, příkaz Turn(...)
na želvě dělá totéž, co Rotate(...)
s útvarem. Pozor - u objektu Shapes
nemáme žádnou vlastnost Angle
, jako má želva,
takže tvar otáčíme vždy vůči jeho současnému natočení! Natočení do výchozí pozice tedy není možné udělat, musíme si vždy pamatovat, o kolik jsme
daný útvar již otočili, pokud to k něčemu potřebujeme.
Příkazem Zoom(jméno, zvětšení-x,
zvětšení-y)
můžeme zmenšovat a zvětšovat tvary. Příkazu jako parametr předáváme hodnotu zvětšení. To je
číslo, které udává, jak moc objekt zvětšíme či zmenšíme. Pokud dáme číslo 1, velikost se nezmění. Pokud dáme číslo větší, než 1, například 2,
objekt se zvětší (v případě 2 se dvakrát zvětší). Pokud dáme číslo menší, než 1, objekt se zmenší. Například číslo 0.5
znamená scvrknutí na poloviční velikost, objekt bude dvakrát menší. Pokud neznáte desetinná čísla, tak je to totéž, co zlomky, jen uděláme vydělení.
Tedy zlomek 1/2 "jedna polovina" je stejný, jako číslo 0.5 (zkuste si to na kalkulačce). Výhoda je, že nemusíme do příkazu psát rovnou výsledek,
můžeme tam samozřejmě napsat přímo výraz, například 1 / 2
, a Small Basic to spočítá sám.
Pokud neznáte ani zlomky, tak si zapamatujte, že dělení menšího čísla větším může být i něco jiného, než "nula zbytek číslo". Pokud budu dělit měnší
číslo větším, dostanu nějaké mezičíslo mezi 0 a 1, které mi u příkazu Zoom(...)
způsobí zmenšení. Pokud budu dělit
Větší číslo menším, bude výsledek samozřejmě větší, než 1, a vznikne zvětšení. Nicméně zvětšování je jednoduché, 2
mi
tvar zvětší dvakrát, 3
třikrát atd.
Jistě vám neuniklo, že příkazu se dává zvlášť zvětšení x a zvětšení y. Protože útvar musí příkaz natáhnout či smrsknout jak ve vodorovném směru (x),
tak ve svislém směru (y), můžeme dát pro každý směr jiné zvětšení. Pokud to uděláme, útvar se nám při zvětšení zdeformuje. Typicky ale budeme dávat
obě čísla stejná, aby útvar měnil jen svou velikost (souměrně), a ne i tvar.
Příkazem SetOpacity(jméno, hodnota)
nastavíme
"neprůhlednost" útvaru. Do parametru hodnota vkládáme čísla 0 - 100. Hodnota 0 znamená, že útvar se stane neviditelným, 100 je výchozí a útvar
normálně vidíme. Všechna čísla mezi značí, že je útvar částečně průhledný, jako duch, a prosvítají skrz něj všechny věci, co jsou pod ním.
Nakonec si představíme ještě příkazy, kterými můžeme zjistit nějaké informace o útvaru. Všechny začínají slovem "Get".
GetLeft(jméno)
nám zjistí, jak je útvar vzdálen od levého okraje grafického okna,
tedy x-ovou souřadnici útvaru.
GetTop(jméno)
nám zjistí, jak je útvar vzdálen od horního okraje grafického okna,
tedy y-ovou souřadnici útvaru.
GetOpacity(jméno)
nám zjistí, jakou hodnotu neprůhlednosti má útvar právě nastavenou.
Příkaz vrací číslo od 0 do 100, kde 0 znamená zcela průhledný a 100 zcela neprůhledný. Viz popis příkazu SetOpacity(...)
pro více informací.
Objekt Controls
představuje tlačítka a textová pole, která je možno vkládat do grafického okna,
a skrz něž může uživatel interaktivně ovládat naši aplikaci klávesnicí a myší.
Budeme si teprve ukazovat.
Objekt ImageList
slouží k načítání obrázků do programu.
Budeme si teprve ukazovat.
Objekt Mouse
představuje myš - ovládací zařízení počítače.
Zvířátko na kreslení čar ve formě tahů je želva - Turtle
.
Na myši máme dvě tlačítka, levé a pravé (samozřejmě i nějaká další, ale ty ve Small Basicu nepoužijeme).
Jsou-li držena uživatelem, objeví se hodnota "True"
("pravda") ve vlastnostech
IsLeftButtonDown
pro levé myšítko či IsRigthtButtonDown
pro pravé. Jinak je ve vlastnostech hodnota"False"
("nepravda").
Myš nám ovládá kurzor na obrazovce. Přes vlastnosti MouseX
a MouseY
můžeme získat jeho pozice. Jedná se o x-ovou a y-ovou souřadnici. Souřadnice jsou podrobně popsány u popisu objektu
GraphicsWindow
. Každopádně MouseX
nám určuje počet barevných bodů,
kolik je kurzor vzdálen od levého okraje monitoru, MouseY
totéž od horního okraje monitoru.
Vlastnostem se dá hodnota i nastavit, takže docílíme toho, že kurzor "teleportujeme" na zadané souřadnice.
Pomocí příkazu HideCursor()
můžeme kurzor skrýt. Myš tam jakoby pořád je, a můžeme s ní hýbat,
ale šipečka představující kurzor zmizí. Samozřejmě to platí jen pro náš program, pokud se v operačním systému přepneme jinam, tak kurzor
opět uvidíme. Pro opětovné ukázání kurzoru zavoláme příkaz ShowCursor()
.
Myš se používá při ovládání grafického okna, a k tomu slouží myšové události a vlastnosti na objektu
GraphicsWindow
. Více tedy přímo u popisu událostí na grafickém okně.
Bude doplněno.
Bude doplněno.
Bude doplněno.
Jak hudbu zapisovat bude doplněno.
K přehrávání piánové hudby slouží příkaz PlayMusic("Notový zápis")
.
Příkaz sice nemá v názvu "AndWait", ovšem příkaz skončí až v momentě, co hudba dohraje. Žádný "asynchronní" příkaz pro hudbu nemáme.
Pokud se chcete pustit do psaní, neváhejte si stáhnout náš tester - Testovací program na PlayMusic, který
pro vás naprogramoval Kryštof.
V programu se nachází velké víceřádkové textové pole, kam je možné psát noty. Tlačítkem "přehrát" pak zapsané noty přehrajete. Jelikož příkaz PlayMusic
nelze nijak zapauzovat, každá skladba musí dohrát, jakmile je spuštěna. Uvnitř programu je to uděláno pomocí techniky "Herní smyčka".
Aby se vám lépe skladby psaly, ve spodní části je nakreslené piánko s názvy not. A zhruba uprostřed se nachází textové pole a tlačítko "Stáhnout". Tím se dá do programu přímo stáhnout skladba, kterou jsme nahráli sem na web. Pokud nějakou skladbičku zapíšete, pošlete nám ji. My ji na web nahrajeme, a každý si ji bude moci stáhnout a přehrát (a samozřejmě vás nemine odměna :)). Dostupné názvy skladeb zobrazíte tak, že na místo jména skladby napíšete "seznam", a měla by se vám (po kliknutí na "Stáhnout") zobrazit zpráva se seznamem názvů. Každý z nich je možné zadat jako název do políčka pro stažení. Pozor, úspěšné stažení přepíše noty, které byly zadané v hlavním textovém poli!
P.S - Ano, i to se dá pomocí Small Basicu dělat. Můžete se klidně podívat na zdrojový kód, jen teda pracuje se v něm s objekty
Network
a File
, které jsme neprobírali.
Objekt Program
představuje náš spuštěný program. Je na něm tedy pár obecných věcí, jež souvisí s celým programem.
Na objektu Program
máme dva jednoduché, ale celkem užitečné příkazy.
End()
okamžitě ukončí program. U Textového okna se neobjeví žádná hláška "press any key", program se "sám odkřížkuje". Veškerý kód, co
následuje, se již nevykoná. Může se hodit v kombinaci s podmínkou, když se stane něco, že už nechceme pokračovat, můžeme takto program zavřít.
Delay(čas)
pozdrží program na zadaný počet milisekund. To je číslo tisíckrát menší, než je sekunda (jako je milimetr a metr). Dá se použít
třeba na odpočítání, viz příklad s proměnnými. Pro pozdržení na dobu jedné sekundy tedy napíšeme
Program.Delay(1000)
Dále máme na objektu vlastnost Directory
, je to vlastnost pouze pro čtení a vyjadřuje nám složku, ve které se nachází
spustitelný soubor (.exe soubor) s naším programem. Ten se nám generuje, kdykoli zmáčkneme tlačítko "Spustit" v softwaru Small Basicu, do stejné složky,
ve které se nachází náš zdrojový kód (soubor .sb), čili složka, kam si program uložíme.
To se hodí k tomu, že můžeme do složky s programem umístit další soubory, které program k běhu potřebuje, například zvuky a obrázky. Ty je pak snadné
načíst, protože jako cestu k nim použijeme právě Program.Directory
, ke kterému přes
zpětné lomeno "\"" připojíme název souboru.
Nejtypičtějším způsobem, jakým se v počítači pracuje s barvami, je tzv. režim 16 milionů barev. Pracuje v něm i Small Basic. My už známe pojmenované barvy, kterými barvíme objekty na grafickém okně. Nás teď bude zajímat prostřední sloupec z tabulky barev - Kód. Každá z těch 16 milionů barev se totiž dá vyjádřit takovýmto šestimístným kódem. Z toho je jasné, že pojmenované barvy ani zdaleka nepostihují celou škálu barev, které můžeme vykreslovat.
Každá barva, kterou na počítači máme, se skládá z červené, modré a zelené složky (Red, Green & Blue = RGB). Mícháním čisté
červené, čisté zelené a čisté modré pak získáme výsledek. Můžete si to vyzkoušet přes tzv. color picker, mě se líbí
tento z webu html color codes. Je tam vybírač barev, a kód vybrané barvy se vám zobrazí
v políčku "Hex".
Nyní si vysvětlíme, jak tyto kódy fungují. Nicméně i bez tohoto vysvětlení je klidně můžete ve vašich programech používat namísto
pojmenovaných barev, například
GraphicsWindow.BrushColor = "#5689A5"
Možná víte, že počítač pracuje ve dvojkové soustavě, zná jen jedničky a nuly. Protože jedička znamená, že elektrický proud teče
a nula znamená, že neteče, jiná možnost není. Tomu říkáme digitální signál, máme buď 1 nebo 0 a nic mezi.
Jednomu čísílku nula či jedna se říká bit.
A teď - možná jste už slyšeli o "bajtech", správně "bytech", resp. o větších kilobajtech, megabajtech atd. Jsou to jednotky
velikosti paměti počítače. Řekli jsme, že počítač pracuje s bity, čili velikost paměti je počet bitů, které se na nějaké
paměťové zařízení počítače vejde.
Jeden byte se skládá z 8 bitů - tedy máme 8 čísílek, u kterých se mohu rozhodnout 0 či 1. Čili mám dvě možnosti pro každé z nich.
Udělám-li 2x2x2x2x2x2x2x2 (vynásobím 8 dvojek za každý bit), dostanu 256. Jeden byte nám tedy umí představovat číslo mezi
0 a 255 (256 možností, jako když je mezi 0 a 9 deset čísel, deset možností).
(Kilobyty jsou pak 1000 bytů, Megabyty 1000 kilobytů atd. Možná jste už slyšeli, že správně je to 1024. A to je skutečně
správnější, pak se to ovšem správně nazývá Kibibyty, Mebibyty atd.)
No a tak se vzalo, že každou složku, červenou, zelenou i modrou, můžeme míchat v rozsahu 1 byte, tedy pro každou složku máme zvlášť možnost vybrat 0 - 255 dílků, které přispějí k finálnímu mixu barev. Čím bude celkově dílků méně, tím tmavší bude barva, čím více, tím světlejší barva. Tedy (0, 0, 0) je úplně černá, (255, 255, 255) je úplně bílá. (255, 0, 0) je čistá červená, (0, 255, 0) čistá zelená a (0, 0, 255) čistá modrá. Čím si jsou čísla blíže, tím je barva více šedá, když jsou stejná, je to vždy nějaký odstín šedé (máme 256 odstínů čistě šedé od bílé po černou). Naopak, když převažuje jedna ze složek, je barva spíše do červena, zelena či modra, když převažují dvě složky, je barva do azurova, purpurova či žluta. (255, 255, 0) je čistá žlutá, (255, 0, 255) je čistá purpurová a (0, 255, 255) je čistá azurová. Tomu se někdy říká doplňkové barvy k červené, zelené a modré (doplněk k RGB je CMY - cyan, magenta a yellow, tedy azurová, purpurová a žlutá).
Dílků máme tedy až 256 ve třech složkách. Vynásobíme-li 256x256x256, dostáváme 16 777 216 kombinací, tedy něco přes 16 milionů.
Proto se také tomuto způsobu tvoření a používání počítačových barev říká režim 16 milionů barev. A skutečně, těch kombinací je
takto "nepřeberné množství". Zbytek textu se zabývá ve zkratce tím, kde se berou ty šestimístné kódy z číslic a písmen. Je to
těžší porce, ale kdo ji pochopí, dokáže správně přečíst a interpretovat význam kódu. Je to také nejrychlejší způsob, jak Small
Basicu barvu předat, přímo textová hodnota s kódem.
Naštěstí máme na grafickém okně příkaz GetColorFromRGB(červená,
zelená, modrá)
, kterému dáme tři čísla v rozmezí
0-255 reprezentující červenou, zelenou a modrou složku cílové barvy, a příkaz nám spočítá a vrátí šestimístný kód
i se znakem #
křížek na začátku. Kód pak můžeme vložit do nějaké barvové vlastnosti.
Pokud se chcete dovědět, jak se číselný kód počítá, přečtěte si i následující text o průhlednosti.
Následující text vysvětluje matematiku za šestimístnými kódy. Je to těžší kus, a je tu spíš pro zajímavost. Pro práci s libovolnými
barvami mimo ty pojmenované stačí znát GetColorFromRGB(...)
, viz předchozí odstavec; nebo
použít nějaký color picker a zjistit si kód barvy vybráním z palety.
A kde se vezme ten šestimístný kód? Když za každou barvu dávám 1 byte, a každý tvoří 8 bitů?
Pro pochopení musí následovat troška matematiky. Všichni dobře známe desítkovou soustavu. Čísla v desítkové soustavě zapisujeme
číslicemi od 0 do 9 (tedy 0,1,2,3,4,5,6,7,8,9), a těch číslic je celkem deset, proto je soustava desítková.
Dokud tedy máme počet devět a menší, vystačíme si s jednou číslicí pro celé číslo. Tomu říkáme jednotky.
Jakmile ale přelezeme desítku, přidám si do čísla další číslici, tedy desítky. Například dvacet sedm věcí zapíšeme jako 27,
tedy máme 2 desítky a 7 jednotek. Tedy vlastně 27 = 2x10 + 7x1 - dvacet sedm je 2 krát desítka a 7 krát jednotka.
Když nám dojdou desítky, přidáme stovky, pak tisíce, desetitisíce a tak dále.
Vidíme, že číslice přidáme vždycky, když se dostaneme k číslu, které je deset krát to, co už jsme měli. Tedy jakmile znovu
vynásobíme číslem naší soustavy, přidáváme číslici - 1 - 10 - 100 - 1000 - 10000 a tak dále.
Teď se podíváme na výše zmiňovanou dvojkovou soustavu. Je dvojková, takže má jen dvě číslice, 0 a 1. S jednotkami tedy zvládneme
zapsat nejvýše číslo jedna, a pak potřebuju přidat číslici. Ale pozor - říkali jsme, že číslici přidáváme, když vynásobíme číslem
naší soustavy. Takže to, co přidáme, nebudou desítky, ale dvojky. Další nebudou stovky, ale čtyřky. Pak osmičky, šestnáctky atd.
Čili opět, jakmile znovu vynásobíme číslem soustavy, což je tentokrát 2, přidáváme číslici - 1 - 2 - 4 - 8 - 16 - 32 - 64 - 128 - 256 - 512 atd.
Zkusme se podívat na číslo ve dvojkové soustavě 1001 = 1x8 + 0x4 + 0x2 + 1x1 - jedna nula nula jedna je 1 krát osmička + 0 krát čtyřka +
0 krát dvojka + 1 krát jednotka. Takže 1001 ve dvojkové soustavě je 9 v desítkové soustavě. Srovnej s příkladem s 27 výše.
Rozeberu tu ještě tu dvacet sedmičku, 27 = 2x10 + 7x1 = 1x16 + 1x8 + 0x4 + 1x2 + 1x1 = 11011. A pozor, nečteme to "jedenáct tisíc jedenáct", ale
"jedna jedna nula jedna jedna".
Zpátky k bytu. Skládá-li se z osmi bitů, skládá se vlastně zároveň z 8 dvojkových číslic. Tedy zprava z jednotek, dvojek, čtyřek, osmiček, šestnáctek, dvaatřicítek, čtyřiašedesátek a stoosmadvacítek. Proto je nejvyšší číslo 255 - když uděláme 128x2, dostaneme 256 a vidíme, že bychom museli přidat devátou číslici reprezentující dvěstěšestapadesátky. Ovšem informatici si vcelku prakticky řekli, že psát kódy barev jako 24 místná čísla z jedniček a nul je nepraktické, a vymysleli zlepšovák.
Pro zlepšovák se musíme podívat na šestnáctkovou soustavu. Pokud jste pochopili povídání doposud, asi vás napadá, jak se to asi
napíše, když bychom potřebovali šestnáct číslic od nuly do patnáctky. Naše arabské číslice jdou ale jen do devítky. Řešení je jednoduché,
použijí se písmenka A - F.
Máme tedy v šestnáctkové soustavě číslice od 0 do F (tedy 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F), a je jich skutečně šestnáct.
Naše známé číslo 27 tak v šestnáctkové soustavě zapíšeme jako 27 = 2x10 + 7x1 = 1x16 + 11x1 = 1x16 + Bx1 = 1B, čteme "jedna bé".
Tedy 1B je 1 krát šestnáctka a B-krát (=11 krát) jednotka.
Číslice přidáváme při násobení 16 - tedy 1 - 16 - 256 - 4096 - 65536 a tak dále.
A teď finální trik. Číslice 0-F nám na jednom místě, jako jednotky, zachytí číslo až do patnáctky. Dvojkové číslo 1111 je ale také patnáct (1x8 + 1x4 + 1x2 + 1x1).
Zároveň je to ale také půlka jednoho byte! Takže můžeme vzít obě půlky každého bytu zvlášť, přečíst je jako čísla ve dvojkové soustavě, zapsat jako šestnáctkovou číslici
a dát to za sebe. Vzkoušejme to opět na našem známém, čísle 27. Mělo by nám vyjít jako 1B, tak schválně, jestli se to povede.
Dvojkový zápis je 00011011 (doplněno na 8 číslic, aby to byl celý byte). Teď číslo roztrhneme na dvě půlky, 0001 a 1011. První půlka, 0001, to je vlastně jen jednotka, takže
výsledek je 1. Druhá půlka, to je 8 + 2 + 1 (1x8 + 0x4 + 1x2 + 1x1), to je jedenáct, takže číslice B. Slepíme k sobě a máme výsledek - 1B. Hurá, všechno funguje.
A tak tedy vzniká šestimístný kód. Do šestnáctkové soustavy se převede hodnota červené složky, zelené složky a modré složky, dá se to za sebe a plácne se před to křížek #.
Mimochodem, to je i vysvětlení, proč ve vybírači barviček najdeme kód jako položku "Hex", je to zkratka anglického slova "hexadecimal", což znamená "šestnáctkový".
Pro pochopení si projděte začátek předchozího textu. Práce s průhlednými barvami je možná, ovšem skýtá několik podivností, proto jsme do ní nepouštěli přímo na kroužku.
Jak už víme, existuje pojmenovaná barva "Průhledná", čili "Transparent". Podle tabulky barev má hodnotu "#00000000"
.
To je nějaké podezřelé, ten kód má 8 šetnáctkových číslic, nikoli 6, jak o tom píšeme všude na této stránce. Ona totiž každá barva má kromě
3 bytů pro barevnou složku ještě jeden byte pro tzv. "alfa" (správně alpha) složku. Té složce se také někdy říká "opacity", česky "neprůhlednost".
Pro všechny pojmenované barvy (mimo průhledné) a pro každou ze 16 milionů barev se šestimístným kódem má tato složka hodnotu plných 255
(čili "FF" šestnáctkově), tedy zcela neprůhledná. Pokud ale chceme mít barvu částečně průhlednou, můžeme dát jinou hodnotu této alfa složce.
S názvem opacity jsme se potkali už u objektu Shapes
, kdy můžeme útvaru jako celku změnit, jak neprůhledný je,
vcelku přímočaře od 0 do 100. Dále jsme v předchozím textu rozebrali, že příkazem
GraphicsWindow.GetColorFromRGB(...)
si můžeme ulehčit získání kódu barvy,
kdy příkazu dáme jen tři čísla reprezentující počet dílků červené, zelené a modré složky, a samotný výpočet šestnáctkového kódu barvy
provede příkaz. U průhledných barev bohužel žádný takovýto komfort nemáme, a tak si musíme spočítat šestnáctkové číslo sami. Naštěstí na to
existuje poměrně jednoduchý trik, který je popsán níže.
V osmimístném kódu barvy je alfa složka jako první. Pro ilustraci tedy napišme například, že
"#5689A5" = "#FF5689A5"
. Obě hodnoty opravdu vyjadřují tutéž barvu,
jak je popsáno v prvním odstavci. Pokud naopak dáme první dva znaky "00", je úplně jedno, co bude následovat, barva se bude vždy
chovat jako průhledná. Mezihodnoty (01 až FE) pak reprezentují nějak průhlednou barvu. Šestnáctkové hodnoty 1 až FE jsou čísla 1 až 254.
Ukážeme si nyní, jak si šestnáctkovou hodnotu spočítat.
Tím, že převádíme čísla menší, než 256, funguje následující matematický trik: Převáděné číslo vydělíme 16 (pod čarou). Výsledek i zbytek převedeme na šestnáctkovou číslici (0-9 je stejné, 10-15 jsou A-F). První číslice je výsledek, druhá zbytek, tím vzniká šetnáctkový kód. Ukažme si konkrétní příklad, zkusíme číslo 186:
186 : 16 = 11 (10) 186 -176 10Výsledek 11 odpovídá číslici B, zbytek 10 číslici A. Číslo 186 je tedy v šestnáctkové soustavě BA.
Jak je možné, že to funguje? Výsledkové číslo má jen dvě číslice, což v šestnáctkové soustavě znamená FF, tedy 255. V desítkové soustavě je to 99,
další číslo, což je 100, už má 3 číslice. Pokud bychom tedy převáděli z desítkové do desítkové soustavy číslo 86, tak 86 : 10 = 8 (6)
,
a stejným postupem vznikne zpátky 86. Pokud bychom ale dělali číslo širší, než 99, museli bychom dělit nejdříve 100 a až pak 10. Pro převod
čísla většího, než 255, do šestnáctkové soustavy, bychom museli dělit nejdříve 256 a až pak 16. To by bylo těžší, dělit pod čarou 256 je "otrava",
ale protože FF je maximum, nemusíme to dělat.
Nyní si ještě vysvětleme záludnosti příkazu GraphicsWindow.GetPixel(...)
. Jak
už víme, zjistí nám barvu pixelu na grafickém okně. Ovšem pouze tehdy, když byl tento pixel pokreslen přímo grafickým oknem. Nevšímá si tedy
barev útvarů objektu Shapes
, barev čas namalovaných želvou nebo barev ovládacích prvků objektu
Controls
. Ignoruje také barvu pozadí - pozadí je speciální vrstva, která se nachází "pod" plátnem grafického okna,
a té můžeme dávat barvu, ale do stavu plátna samotného nezasahuje. Je to logické - při změně barvy plátna nedojde k překrytí vykreslenců novým
pozadím. Jak také víme, u nevykreslených pixelů nám příkaz vrátí #000000, tedy černou. Oni jsou ty pixely ve skutečnosti průhledné, ovšem průhlednost
nám GetPixel()
ignoruje.
A to je poslední záludnost. Barvu s průhledností samozřejmě můžeme nastavit Peru a Štětci grafického okna. Ostatně jsme to už dělali, když jsme nastavovali
štětec jako "Transparent"
, aby se nám útvary přidávaly jen jako rámečky (u objektu Shapes, proto mluvíme o přidávání).
U přidávání to tedy funguje, a světe div se, funguje to i u vykreslování (Fill a Draw). Ovšem GetPixel()
průhlednost
ignoruje, jak už víme. Pokud tedy zajistíme barvu nějakého zčásti průhledného pixelu, vrátí se nám úplně jiná barva, než ta, kterou měl štětec/pero, co
vykreslilo zjišťovaný pixel.
Představme si, že pixel byl vykreslen štětcem, který měl hodnotu "#80FF0000". Tedy přesně napůl průhlednou čistě červenou barvu. Intuitivní by zřejmě bylo,
aby GetPixel()
vrátil "#FF0000" (tedy totéž, co "#FFFF0000"), tedy že by alpha složku prostě vyignoroval. Nebo, že by se podíval
na barvu pozadí, tu by namíchal podle alpha složky (tedy v našem případě půl na půl) s barvou pozadí a vrátil tento mix.
Bohužel se neděje ani jedno. Příkaz částečně průhlednou barvu opravdu namíchá a vrátí nám hodnotu mixu, ale nikoli s barvou pozadí. Vždy s ČERNOU
barvou #000000. Což je trochu neintuitivní, když většinou máme bílé pozadí. Vrácená barva GetPixelem bude tak #800000, tedy tmavě čistě červená
(poloviční červená). Naprotitomu mix s bílou barvou by byl #FF8080, což je světlá červená (a tedy opravdu napůl míchaná čistá červená s bílou).
Ten však nedostaneme, jak jsme již řekli, takže bychom si výpočet mixu s pozadím museli doprogramovat sami, pokud bychom to potřebovali.