Pravouhlé 70s
V predošlom tutoriáli Lomená čiara sa lomená čiara šírila do okolia náhodne ľubovoľným smerom. Ak by sme chceli docieliť pravidelnejší vzhľad, obmedzíme smer pohybu len na 4 možnosti: doprava, doľava, nahor, nadol.
A aby sme to vizuálne ozvláštnili, budeme namiesto čiary kresliť farebné kruhy s estetikou 70-tych rokov:

Základný program
Základ je štandardný skeč so setup
a draw
. Budeme tiež potrebovať:
Súradnice
x
,y
, ktoré hovoria, kde sa práve nachádzame.Krok
k
, ktorý definuje o koľko pixlov sa v každom kroku pohnemeVeľkosť
v
, ktorá definuje veľkosť vykresľovaného krúžku.
float x,y;
float k = 40;
float v = 40;
void setup()
{
size(800,400);
background(#C1973B);
noStroke();
x = width/2;
y = height/2;
}
void draw()
{
circle(x,y,v);
}

Smer
V tutoriáli Lomená čiara bola zmena smeru úplne náhodná v celom ľubovoľnom okolí začiatočných súradníc čiary. Teoreticky to bolo nekonečne veľa možností. Ak sa chceme hýbať len v 4 smeroch, budeme náhodný smer generovať inak. Vyrobíme si globálnu premennú smer
a tá bude mať hodnoty: 0 pre smer doprava, 1 pre smer nadol, 2 pre smer doľava, 3 pre smer nahor.
float x,y;
float k = 40;
float v = 40;
int smer = 0;
V závislosti od toho, akú hodnotu má smer
, budeme posúvať súradnice x
,y
doprava, nadol, doľava alebo nahor. Ak je smer
rovný 0, zväčšíme x
o krok k
. Ak je smer rovný 1, zväčšíme y
o krok k
. A tak ďalej.
Štandardne by sme toto vetvenie začali písať nejak takto:
if (smer == 0)
{
x = x + d
}
else if (smer == 1)
.....
A postupne by sme takto rozvetvili všetky 4 možnosti smerovania. Ale museli by sme písať vela ifov a veľa elsov. Ukážeme si niečo lepšie.
Vetvenie cez switch
switch
Ak chceme vetviť na základe niečoho, čo má len obmedzený počet hodnôt - ako napríklad naša int
premenná s názvom smer
- tak je praktické použiť takéto vetvenie:
void draw()
{
circle(x,y,v);
// Pohyb v smere
switch(smer)
{
case 0:
x = x + k;
break;
case 1:
y = y + k;
break;
case 2:
x = x - k;
break;
case 3:
y = y - k;
break;
}
}
Ako parameter do príkazu switch
dáme premennú, na základe ktorej sa chceme prepínať medzi rôznymi variantami. U nás je to smer
.
Každú jednu variantu napíšeme ako jeden case
. Naša varianty hodnôt premennej smer
sú 0
,1
,2
,3
, tak pre každú máme jeden case
. Každý case
je ukončený príkazom break
. Na toto pozor, ak by ste zabudli break
, program bude robiť hlúposti.
Všimnite si tiež, že všetky prípady case
tvoria spolu jeden blok ohraničený zátvorkami {
,}
.
Krúžky sa teraz rozbehnú doprava, lebo máme smer
nastavený na začiatku na hodnotu 0
a nijak ho zatiaľ nemeníme:

Môžete vyskúšať, či vám dobre fungujú aj iné smery, ak zmeníte default hodnotu premennej smer
na 1
alebo 2
alebo 3
. Tiež si všimnite, že budeme potrebovať dorobiť ešte loopovanie obrazovky, aby nám krúžky neutiekli úplne von.
Podprogramy
Celkovo nás ešte čakajú minimálne dva dlhšie kusy kódy: zmena smeru a loopovanie obrazovky. Aby sme nemali draw
dlhočizný a neprehľadný, tak si upraceme kód pomocou podprogramov.
Začneme tým, že celý switch
, ktorý nám robí posun premiestnime do podprogramu pohni
:
void pohni()
{
switch(smer)
{
case 0:
x = x + k;
break;
case 1:
y = y + k;
break;
case 2:
x = x - k;
break;
case 3:
y = y - k;
break;
}
}
void draw()
{
circle(x,y,v);
// Pohyb v smere
pohni();
}
A rovno si vyrobme aj (zatiaľ prázdne a ničnerobiace) podprogramy pre zaloopovanie obrazovky a zmenu smeru.
void zmen_smer()
{
}
void zaloopuj()
{
}
void draw()
{
circle(x,y,v);
// Pohyb v smere
pohni();
// Zaloopuj obrazovku
zaloopuj();
// Zmena smeru
zmen_smer();
}
Takto štruktúrovaný program sa ľahšie číta, náš draw
má len pár riadkov a jednotlivé logické celky: hýbanie súradnicami, ich zacyklenie, keď vylezú z obrazovky, a zmena smeru sú navzájom oddelené, každý vo svojom vlastnom podprograme.
Zmena smeru
Smer chceme meniť tak, aby zahýbal v pravom uhle. Takže ak je terajší smer doprava, tak nový smer bude buď nahor alebo nadol. Ak je terajší smer nadol, tak nový smer bude buď doľava alebo doprava. A tak podobne pre zvyšné dva smery.
Náhodný výber z dvoch možných smerov (napríklad výber z 1 a 3) vieme urobiť takto:
if (random(1) > 0.5)
{
smer = 1;
}
else
{
smer = 3;
}
// ^--- toto zatial do kodu nevkladajte, je to len na ukazku.
Príkaz random(1)
vygeneruje náhodné desatinné číslo medzi 0 a 1. A keď sa v podmienke if
spýtame, či je toto náhodné číslo väčšie ako 0.5
, tak s pravdepodobnosťou 50:50 budeme náhodne priraďovať smer
u raz hodnotu 1 a inokedy hodnotu 3.
Takto by sme vedeli napísať zmenu smeru pre všetky 4 varianty:
Ak je terajší smer
rovný 0
, vyberáme z 1
a 3
.
Ak je terajší smer
rovný 1
, vyberáme z 0
a 2
.
Ak je terajší smer
rovný 2
, vyberáme z 1
a 3
.
Ak je terajší smer
rovný 3
, vyberáme z 0
a 2
.
Použijeme teda opäť vetvenie cez switch
na tieto 4 varianty náhodného výberu.
Ale s drobnou optimalizáciou. V prípade 0 a v prípade 2 vyberáme z tých istých nových smerov: 1 a 3. A analogicky v prípade 1 a v prípade 3 vyberáme z tých istých nových smerov: 0 a 2.
Toto vieme vo vetvení switch
urobiť tak, že združíme rovnaké varianty case
-y pod seba:
void zmen_smer()
{
switch (smer)
{
case 0:
case 2:
if (random(1) > 0.5)
{
smer = 1;
}
else
{
smer = 3;
}
break;
case 1:
case 3:
if (random(1) > 0.5)
{
smer = 0;
}
else
{
smer = 2;
}
break;
}
}
Smer sa už teraz mení a krúžky sa hýbu do rôznych strán:

Zaloopovanie
Loopovaniu obrazovky, aby súradnice vylezené na jednom okraji von z okna sa objavili na opačnom okraji okna, sme sa už venovali pri Lomenej čiare. Tu pre stručnosť len uvediem kód podprogramu zaloopuj
:
void zaloopuj()
{
if (x < 0)
{
x = x + width;
}
if (x > width)
{
x = x - width;
}
if (y < 0)
{
y = y + width;
}
if (y > height)
{
y = y - height;
}
}

Zmena smeru len občas
V takejto podobe programu sa zmena smeru deje v každom jednom draw
. Výsledkom je namiesto súvislejšieho pohybu jedným smerom len chaotický pohyb v najbližšom okolí.
Vyriešime to tak, že zmenu smeru nebudeme vykonávať v každom jednom draw
, ale povedzme len každých 5 draw
-ov.
Na to si budeme musieť v nejakom počítadle ukladať, koľko krát už prebehol draw.
Vytvorte globálnu premennú pocitadlo
a nastavte ho na 0
:
float x,y;
float k = 40;
float v = 40;
int smer = 0;
int pocitadlo = 0;
A potom v draw
budeme zvyšovať počítadlo o 1 a zavrieme zmenu smeru do podmienky, ktorá nastane len ak je pocitadlo
rovné 5
:
void draw()
{
pocitadlo++;
if (pocitadlo == 5)
{
// Zmena smeru
zmen_smer();
}
circle(x,y,v);
// Pohyb v smere
pohni();
// Zaloopuj obrazovku
zaloopuj();
}
Zmena smeru naozaj nastala až po piatich vykresleniach:

Akurát zmena smeru nastala iba jeden raz a potom už nikdy. Prečo? Pretože pocitadlo
na začiatku rástlo, dorástlo do 5, nastala zmena a potom rástlo ďalej na 6,7,8.... a už nikdy znova nenastala situácia, že by bolo rovné 5.
Preto ho musíme zresetovať naspäť na 0 vždy, keď dosiahne 5:
void draw()
{
pocitadlo++;
if (pocitadlo == 5)
{
// Zmena smeru
zmen_smer();
// Zresetuj pocitadlo
pocitadlo = 0;
}
circle(x,y,v);
// Pohyb v smere
pohni();
// Zaloopuj obrazovku
zaloopuj();
}

Farby ako zo 70s
Aby sme mali farby pekné ako zo 70s, tak využijeme to, že červené, oranžové a hnedé farby sa vyskytujú na dolnom konci tónov HSB modeli. Preto prepneme skeč do HSB módu:
void setup()
{
size(800,400);
background(#C1973B);
noStroke();
x = width/2;
y = height/2;
colorMode(HSB);
}
A budeme pre každý krúžok generovať farbu, ktorá má H náhodné z rozsahu 0 až 40, sýtosť S má plných 255 a svetlosť B má náhodnú, aby nám vznikali aj tmavé odtiene.
fill(random(40), 255, random(256));
circle(x,y,v);

Náhodná dĺžka segmentov
Tým, že zmena smeru sa deje vždy po 5 vykresleniach, tak jednotlivé 5-dielne segmenty tvoria pravidelnú mriežku. Poďme to znáhodniť, aby sa zmena nediala vždy pravidelne po 5 opakovaniach, ale aby počet opakovaní bol nejaké náhodné číslo z rozsahu 5 až 10.
Teraz je 5ka natvrdo v kóde. Prvá zmena, čo musíme urobiť, je vytiahnuť ju do premennej. Nazvime si premennú dlzka
:
float x,y;
float k = 40;
float v = 40;
int smer = 0;
int pocitadlo = 0;
int dlzka = 5;
A zmeniť aj podmienku v draw
:
void draw()
{
pocitadlo++;
if (pocitadlo == dlzka)
{
// Zmena smeru
zmen_smer();
// Zresetuj pocitadlo
pocitadlo = 0;
}
fill(random(40), 255, random(256));
circle(x,y,v);
// Pohyb v smere
pohni();
// Zaloopuj obrazovku
zaloopuj();
}
A vždy, keď nastane zmena smeru, tak si náhodne určíme novú hodnotu dĺžky:
void draw()
{
pocitadlo++;
if (pocitadlo == dlzka)
{
// Zmena smeru
zmen_smer();
// Zresetuj pocitadlo
pocitadlo = 0;
// Nova dlzka segmentu
dlzka = int(random(5,10));
}
fill(random(40), 255, random(256));
circle(x,y,v);
// Pohyb v smere
pohni();
// Zaloopuj obrazovku
zaloopuj();
}

Náhodná veľkosť
Posledná úprava je, aby krúžky mali náhodnú veľkosť. Teraz máme veľkosť uloženú v premennej v
, ktorá je inicializovaná na hodnotu 40, ale nikde ju už potom nemeníme.
Nastavme jej náhodnú hodnotu tiež pri každej zmene smeru:
void draw()
{
pocitadlo++;
if (pocitadlo == dlzka)
{
// Zmena smeru
zmen_smer();
// Zresetuj pocitadlo
pocitadlo = 0;
// Nova dlzka segmentu
dlzka = int(random(5,10));
// Nova nahodna velkost
v = random(5,40);
}
fill(random(40), 255, random(256));
circle(x,y,v);
// Pohyb v smere
pohni();
// Zaloopuj obrazovku
zaloopuj();
}
A to je hotovo:

Tu je finálny skeč:
Last updated