Atramentová krivka
Last updated
Last updated
Nadviažeme voľne na tutoriál Lomená čiara a vyrobíme si nekonečnú farebnú krivku. Ale namiesto ostrých zlomov bude mať plynulý priebeh. A doplníme jednoduchý efekt na rozmazávanie obrazovky:
Začneme so štandardným skečom so setup()
a draw()
, nič špeciálne.
Lomenú čiaru predtým sme vyrábali so segmentou na seba nadviazaných. Každý segment bola jedna krátka úsečka. Tu budeme na seba nadväzovať krátke krivky.
beginShape()
a endShape()
Aby sme mohli kresliť krivku, už nám nebude stačiť obyčajný príkaz line()
ale naučíme sa univerzálnejší postup, ktorý vie nakresliť aj tvary z viacerými vrcholmi alebo zaoblené krivky.
Vyskúšajte tento skeč:
Vykreslí to trojuholník. Skúste za tretí príkaz vertex()
pridať ďalší príkaz vertex()
s nejakými svojimi súradnicami. Vykreslí sa štvoruholník. Skúste pridať ďalší vertex. Vykreslí sa päťuholník.
Takto vieme, okrem iného, vykresliť ľubovoľný n-uholník. Každý jeho vrchol má svoj príkaz vertex()
.
Cez príkazy beginShape()
a endShape()
vieme kresliť aj zaoblenú krivku, takzvanú Bézierovu. Tá pozostáva zo 4 bodov. V prvom bode začína, druhý a tretí bod určujú jej zaoblenie, vo štvrtom bode končí:
Vyrobíme si v skeči súradnice pre 4 body abcd a len tak na skúšku priraďme im nejaké súradnice:
Takto potom vykreslíme medzi týmito 4 bodmi krivku:
Prvý vertex()
určuje, odkiaľ krivka začína (bod a). A súradnice ďalších 3 bodov sú potom v nasledujúcom príkaze bezierVertex()
. Program sa dá čitať tak, že začni v bode ax
,ay
a potom urob krivku cez body bx
, by
, cx
, cy
až do bodu dx
, dy
.
Ak by sme dali krivke úplne náhodné súradnice, tak bude dosť veľká divoká. Vyskúšajte v setup()
namiesto konkrétnych čísel priradiť x-ovým súradniciam random(width)
a y-ovým súradniciam random(height)
.
My chceme, aby naša veľká krivka bola vyskladaná s malých segmentov. Takže upravíme súradnice tak, aby bod B bol v blízkom okolí bodu A, bod C v blízkom okolí bodu B a bod D v blízkom okolí bodu C. V akom blízkom? Na to si vyrobíme premennú v
(ako vzdialenosť):
Generovanie náhodnej pozície v okolí inej pozície sme už robili pri Lomenej čiare, tu je to podobné. Začneme v strede obrazovky a ďalšie súradnice generujeme v okolí tých predošlých:
Nová krivka je už krátka a dobre sa nám tak budú skladať segmenty:
Ak budeme chcieť kresliť ďalšie a ďalšie segmenty, tak budeme potrebovať, aby nový segment začínal tam, kde skončil predošlý. Takže po vykreslení si ax
,ay
nastavíme na dx
,dy
a ostatné súradnice vygenerujeme znova náhodne:
Jednotlivé segmenty na seba náhodne nadväzujú, ale sú dosť kostrbaté. To preto, že na seba nenadväzujú hladko. Nový začiatok A je síce umiestnený tam, kde bol starý konec C, ale inak je krivka inak zaoblená. Takto to vyzerá zväčšené. Šípka označuje nadpojenie nového segmentu na starý.
Aby bolo napojenie hladké, musíme prispôsobiť nie len nový začiatok A starému koncu D, ale aj nové zaoblenie B starému koncu. Konkrétne takto:
Nová krivka je už o poznanie hladšia:
Ak si všimnete, tak náhodné pozície C a D generujeme dvakrát úplne rovnako. Raz na konci v setup()
a druhý raz na konci v draw()
. Je to zbytočné a postačí, keď ich budeme generovať iba raz, a to na začiatku draw()
:
Keď nám vylezie krivka von z okna, chceme ju vrátiť naspäť na opačnom okraji obrazovky. Pri lomenej čiare, stačilo prehodiť na opačný koniec obrazovky jeden bod. Tu máme ale krivku, tak budeme prehadzovať na opačný koniec dva body: A aj B.
Vyrobíme si na to podprogram zaloopuj()
, aby sme nemali už moc komplikovaný draw()
:
A podprogram potom zavoláme na konci draw()
:
Geometriu máme vyriešenú, poďme dekorovať. Nastavme farebný režim na HSB a pozadie na čierne:
A v draw()
budeme pred každým vykreslením postupne posúvať farebný tón. V minulosti by sme si vyrobili časovú premennú t
a zvyšovali ju na konci draw()
o nejakú hodnotu. Ale ukážeme si iný spôsob.
Processing nám v systémovej premennej frameCount
hovorí, koľký krát sa práve vykresľuje draw()
. Koľký snímok v poradí sa práve vykresľuje. Preto frameCount
. Na začiatku je v tejto premennej uložená hodnota 1
a po každom draw()
sa automaticky zvyšuje o 1.
Použijeme ju teda na nastavenie farby pred vykreslením segmentu krivky:
Akurát, že po istom čase je už krivka len červená, lebo nám frameCount
vyliezol nad hodnotu 255
. Tak ho po dosiahnutí 256
zrazíme naspäť na nulu pomocou %
:
Zaujímavý efekt ako pri písaní štetcom docielime, ak budeme náhodne meniť hrúbku čiary pre každý segment:
image()
Na záver ešte dorobíme vizuálny efekt, kedy sa vykreslený obraz postupne zväčšuje a tým aj rozostruje. Toto vyrobíme tak, že na konci každého draw()
si uložíme do premennej celý obsah obrazovky a na začiatku ďalšieho draw()
ho vykreslíme trochu zväčšený a trochu posunutý.
Vyrobíme si na to premennú špeciálneho typu PImage
, do ktorej sa dá uložiť obrázok.
Na konci draw()
si do premennej img
uložíme obsah obrazovky jednoduchým príkazom get()
:
Na začiatku draw()
vykreslíme obrázok uložený v premennej img
príkazom image()
. Akurát, v úplne prvom draw()
ešte nie je v img
nič uložené, tak počítač by sa hneval. Aby sa to nedialo, tak si to ošetríme podmienkou, že img
sa vykresľuje iba, ak už som v neskoršom frame ako v prvom. Využijeme na to frameCount
, ktorý si pamätá, v ktorom frame teraz sme.
Príkaz image()
má niekoľko parametrov. Prvý je obrázok, ktorý sa má vykresliť. Druhý a tretí parameter sú súradnice, odkiaľ sa má obrázok začať vykresľovať. Dali sme tam zatiaľ 0
,0
a preto sa nič nedeje. Obrázok na konci zosnímame z obrazovky a na začiatku ho vykreslíme do ľavého horného rohu obrazovky. Presne na to isté miesto, odkiaľ sme ho zobrali. Preto sa nič viditeľné nedeje.
Skúste upraviť volanie príkazu image()
takto:
Obrázok bude ubiehať doprava dole:
Ak chceme, aby sa postupne zväčšoval, tak urobíme dve veci:
Začneme ho vykresľovať nie od 1,1 ale od -1,-1, takže bude začínať trochu mimo obrazovky vľavo hore
A vykreslíme ho väčší o 2 pixely než je obrazovka, takže bude končiť trochu mimo obrazovky vpravo dole.
Na nastavenie veľkosti vykresľovaného obrázka slúži tretí a štvrtý parameter v image()
:
Toto je už efekt zväčšovania a s tým aj spojené rozostrenie, lebo obrázok je pixelový a pri jeho zväčšovaní dochádza k strate kvality:
Tu si môžete stiahnuť finálny skeč: