Harjoitus
Piirrä draw-metodissa pisteitä (point) sattumanvaraisilla koordinaateilla. Pidä kuitenkin huoli, että pisteet osuvat ikkunan alueelle.
Edellisessä luvussa tutustuit Processinging setup() ja draw() -metodeihin. Nyt pääset vihdoin luomaan liikettä töihisi käyttämällä satunnaisuutta draw-metodin komennoissa!
Aiemmin olet määritellyt metodien parametrien arvot kiinteillä
lukuarvoilla. Parametrit ovat olleet muuttumattomia ohjelman jokaisella
suorituskerralla. Eli esimerkiksi komento ellipse(0,0,100,100)
piirtää
läpimitaltaan sadan pikselin ympyrän ruudun vasempaan ylänurkkaan
jokaisella suorituskerralla. Jos arvoja muutetaan, ympyrä tulee
piirretyksi eri kohtaan ruutua.
Kokeile nyt lisätä satunnaisuutta tämän yksinkertaisen esimerkin avulla. Ohjelma arpoo point-metodin parametreiksi satunnaisen x- ja y-koordinaatin random-metodin avulla:
void setup(){
// täällä oleva koodi suoritetaan vain kerran
}
void draw(){
// täällä oleva koodi suoritetaan oletusarvoisesti
// 60 kertaa sekunnissa kunnes ohjelma suljetaan
point(random(100), random(50, 100));
}
Processing suorittaa draw-metodin ja sen sisältämät komennot yhä uudestaan ja uudestaan ohjelman suorituksen aikana. Jokaisen kerran kun draw-metodi suoritetaan, kirjoittamasi ohjelma piirtää pisteen ruudulle. Koska piste saa sattumanvaraiset parametrit koordinaateiksi, piste piirretään jokaisella kierroksella eri kohtaan ruutua.
Random-metodin parametriksi annetaan arvottavan luvun minimi ja maksimi. Jos parametreja on vain yksi, arvotaan luku nollan ja annetun parametrin välillä. Nyt koodi arpoo siis x-koordinaatin arvoksi luvun väliltä 0-100 ja y-koordinaatin arvoksi luvun väliltä 50-100:
X- tai y-koordinaatin sijaan voit korvata minkä tahansa parametrin arvon random-metodilla!
Random-metodi palauttaa satunnaisen desimaaliluvun, joka puolestaan annetaan parametrina point-metodille (eli random-metodi on tyyppiä float). Metodeja, jotka palauttavat jonkin arvon (eli jotka eivät ole tyyppiä void), voidaan siis käyttää parametreina toisen metodin sisällä, aivan kuten tässä käytimme random-metodia point-metodin parametrina. Perehdymme tyyppeihin lisää myöhemmin.
Alla oleva kuva selventää, mistä osista rect-metodin kutsu koostuu, kun sen sisältä kutsutaan random-metodia.
Oletusarvoisesti ruutu päivittyy 60 kertaa sekunnissa. Voit vaikuttaa ruudun päivitysnopeuteen frameRate-metodin avulla. Seuraavassa esimerkki havainnollistaa random-metodin toimintaa hidastamalla ruudun päivitystiheyttä.
Asetetaan aluksi ruudun koko hieman suuremmaksi size-metodilla ja asetetaan valkoinen tausta background-metodilla. Asetetaan sitten frameRate -metodin arvoksi 1, mikä tarkoittaa sitä, että ruutu päivitetään kerran sekunnissa. Tulostetaan lopuksi konsoliin (musta laatikko IDE:n alareunassa) teksti, joka ilmoittaa setup-metodin olevan valmis. Näitä metodeja kutsutaan setup-metodin sisällä, joten ne suoritetaan vain kerran ohjelman alussa.
void setup(){
size(500, 500);
background(255);
frameRate(1);
println("setup suoritettu!");
}
void draw(){
ellipse(random(width), random(height), 20, 20);
println("Ruutu päivitetty " + frameCount + " kertaa");
}
Draw-metodin sisältö suoritetaan nyt siis 60 kerran sijaan vain kerran sekunnissa. Eli kerran sekunnissa piirretään ympyrä satunnaiseen kohtaan ruutua ja tulostetaan konsoliin teksti, montako kertaa draw-metodin sisältö on suoritettu ohjelman käynnistämisestä alkaen.
Kopioi ja suorita ylläoleva ohjelma. Kokeile myös muuttaa frameRate-metodin parametria pienemmäksi tai suuremmaksi. Kuinka usein ruutu päivitetään, jos se päivitetään 0.2 kertaa sekunnissa?
Huomaa, että println-metodi on melko hidas eikä välttämättä pysy isommilla arvoilla ihan mukana suoritustahdissa. Tärkeää on hahmottaa random-metodin toiminta ja se, miten draw-metodi suoritetaan yhä uudestaan ja uudestaan kunnes ohjelman suoritus lakkaa.
Width, height ja frameCount ovat muuttujia. Muuttujiin tutustutaan tarkemmin seuraavassa kappaleessa. Tällä hetkellä riittää tietää, että:
Tämä helpottaa ohjelmointia, sillä voit esimerkiksi piirtää jotakin kohtaan (width/2, height/2), joka on aina ruudun keskellä riippumatta ruudun koosta. Näin voit myöhemmin muuttaa ruudun kokoa ilman että piirtokoodia täytyy korjata useammasta kohdasta.
Voit tyhjentää ruudun joka ruudun päivityksellä kutsumalla background-metodia draw-metodin sisällä:
void setup(){
size(500, 500);
background(255);
frameRate(1);
}
void draw(){
background(255);
ellipse(random(width), random(height), 20, 20);
}
Background-metodi täyttää ruudun annetulla värillä ja kaikki aiemmin ruudulle piirretty peittyy. Esimerkistä voit huomata, että vain uusin, viimeisimmässä draw-metodissa suoritettu ympyrä jää näkyviin. Kaikki muut peittyvät valkoisen taustan alle.
Entä jos haluatkin häivyttää piirrettyjä ympyröitä vain hiukan täyden
peittämisen sijaan? Luonnollinen idea voisi olla läpinäkyvän värin
käyttäminen background-metodin värinä: background(0, 15);
Ikävä kyllä
tämä ei toimi: background-metodi ei voi käyttää täyttövärinään
läpinäkyvää väriä. Tämä liittyy Processinging tapaan piirtää asioita
näytölle. Ratkaisuna voit kuitenkin piirtää draw-metodin alussa koko
ruudun kokoisen nelikulmion, jonka täyttöväri on läpinäkyvä:
void setup(){
size(500, 500);
background(255);
frameRate(1);
}
void draw(){
fill(255, 50);
rect(0, 0, width, height);
ellipse(random(width), random(height), 20, 20);
}
Ohjelma piirtää jokaisen draw()-metodin suorituksen alussa koko ruudun peittävän nelikulmion, joka läpinäkyvyytensä ansiosta peittää osin alleen kaiken aiemmin piirretyn. Lopputuloksena on vaikutelma ruudun asteittaisesta häivytyksestä:
Kun kutsut metodeja setup- ja draw-metodien sisällä, muuttuu ohjelman rakenne heti ratkaisevasti monimutkaisemmaksi. Siksi on tärkeää pitää koodi luettavana ja selkeänä. Erityisen tärkeää on sisentäminen, joka auttaa hahmottamaan, missä suhteessa metodit ovat toisiinsa nähden. Voit sisentää välilyönneillä tai tabeilla, kunhan kaikki on sisennetty samalla tavalla. Mikäli huomaat koodisi sisennysten menneen pahasti sijoiltaan, voit myös käyttää IDE:n auto format -työkalua painamalla ctrl + t.
Koodin pitäminen siistinä helpottaa ohjelmointia huomattavasti. Kumpaa allaolevista koodinpätkistä on mielestäsi mukavampaa lukea?
void setup() {
size(500,500);
background (255);
frameRate(1);
println("setup suoritettu!");
}
void draw() {
fill(255, 255, 255, 50);
rect(0,0,width,height);
ellipse(random(width),random(height),20, 20);
println("Ruutu päivitetty "+frameCount+" kertaa");
}
void setup() {
size(500, 500);
background(255);
frameRate(1);
println("setup suoritettu!");
}
void draw() {
fill(255, 255, 255, 50);
rect(0, 0, width, height);
ellipse(random(width), random(height), 20, 20);
println("Ruutu päivitetty " + frameCount + " kertaa");
}