7.3 Omat funktiot
Yhteenveto
Tehdään kaksi aliohjelmaa. Toinen piirtää ympyrän, kun annamme sille keskipisteen ja säteen. Toinen aliohjelma, piirtää neliön, kun annamme sille keskipisteen ja neliön sivun pituuden.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
void setup () {
size(400,400); // Ikkunan koko
background(255); // Valkea taustaväri
fill(255,0,0); // Punainen täyttöväri
}
void draw() {
ympyra(100,100,50);
nelio(250,250,200);
}
void ympyra(int x, int y, int r) {
ellipse(x,y,2*r,2*r);
}
void nelio(int x, int y, int r) {
rect(x-r/2,y-r/2,r,r);
}
Aliohjelma eli funktio
Haluamme luoda oman komennon ympyra(x,y,r); missä (x,y) on ympyrän keskipiste, r on ympyrän säde. Kuinka se onnistuu? Tällöin sanotaan, että luodaan aliohjelma eli funktio, jota pääohjelmasta void draw () kutsutaan nimellä. Aliohjelma, joka piirtää ympyrän, on seuraavanlainen.
void ympyra(int x, int y, int r) {
ellipse(x,y,2*r,2*r);
}
Ympyrä piirretään ellipse(x,y,a,b); komennon avulla, missä (x,y) on ellipsin keskipiste ja a on ellipsin leveys ja b on ellipsin korkeus. Jos säde on r, niin ellipsin leveys ja korkeus ovat tällöin 2*r. Nyt voimme ellipse(x,y,a,b)-komennolla piirtää ympyrän.
Jos ajat ohjelman, niin mitään ei tapahdu. Miksi? Oma komento ympyra(x,y,r); suoritetaan vain pääohjelmasta kutsumalla eli funktiosta: void draw (); Sanotaan, että funktiota tällöin kutsutaan. Vuorovaikutus pääohjelman ja aliohjelman välillä on seuraava.

Kokonainen ohjelma on seuraavanlainen.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
void setup () {
size(400,400); // ikkunan koko
background(255); // Valkea taustaväri
fill(0,255,0); // Vihreä täyttöväri
}
void draw() {
ympyra(200,200,50); // Aliohjelman kutsuminen
ympyra(300,100,20); // Kutsutaan aliohjelmaa toisen kerran.
}
void ympyra(int x, int y, int r) {
ellipse(x,y,2*r,2*r);
}
Kun ajat ohjelman, niin se näyttää tältä.

Kuten huomaat, aliohjelmaa voidaan kutsua pääohjelmasta niin monta kertaa kuin haluat. Aliohjelmat mahdollistavat jo käytössä olevien piirtokomentojen suomentamisen, mutta voit luoda mihin tarkoitukseen tahansa oman aliohjelman eli funktion. Omien funktioiden eli aliohjelmien käyttäminen lyhentää pääohjelmaa ja ongelma saadaan pilkottua osiin.
Yleisesti aliohjelma muodostetaan seuraavan rakenteen mukaisesti.
void aliohjelman_nimi (aliohjelman_muuttujat) {
Komennot;
}
Tässä sana void tarkoittaa sitä, että funktio ei palautua mitään arvoa, vaan funktio suoritetaan itsenäisenä. Seuraavassa kappaleessa tutkitaan funktioita, jotka palauttavat arvoja takaisin pääohjelmaan.
Kuten huomaat, myös lohkot void setup () ja void draw () ovat funktioita. Sekä kaikki aikaisemmin käydyt piirtokomennot. Nämä funktiot on piilotettu ohjelman mukana latautuviin kirjastoihin.
Aliohjelmien nimeämisessä on samat käytännöt kuin muuttujien nimeämisessä. Käytännössä tämä tarkoittaa sitä, että aliohjelmien nimessä et voi käyttää skandimerkkejä (ö,ä,å), erikoismerkkejä, etkä välilyöntejä.
Aliohjelmassa translate(x,y) ja scale(koko); -komennot
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
void setup() {
size(400, 400); // Ikkunan koko
background(255); // Taustaväri valkoinen
fill(255,0,0); // Täyttöväri punainen
}
void draw() {
ympyra(110, 110,20); // Kutsutaan aliohjelmaa
ympyra(180, 110,50);
}
void ympyra(int x, int y, int r) {
pushMatrix(); // Otetaan nykyinen koordinaatisto muistiin
translate(x, y); // Siiretään origo pisteeseen (x,y)
scale(2*r/100.0); // Skaalataan kuviota isommaksi tai pienemmäksi.
ellipse(0,0,100,100); // Piirretään origoon ympyrä, jonka halkaisija on 100
popMatrix(); // Palautetaan koordinaatisto takaisin
}
Ohjelman tulostus on seuraavanlainen.

Piirretään origoon ympyrä, jonka halkaisija on 100 px. Tässä ympyrä siirretään eri paikkaan translate(x,y); komennolla ja kuvion koko saadaan isommaksi scale(2*r/100.0); komennolla. Huomaa, että laskukaava 2*r/100.0 on kerroin, kuinka moninkertaiseksi kuvio skaalataan. Jos kerroin on yli yksi, kuvio suurenee alkuperäisestä (100 px). Jos kerroin on alle ykkösen, niin kuvio pienenee alkuperäisestä (100 px).
Nyt emme tarvitse välittää koordinaattitietoja, sekä kokotietoja ellipse(x,y,a,b); funktioon. Tämä oivallus helpottaa monimutkaisten kuvioiden siirtämistä ja suurentamista eri paikkaan. Koska kuvion paikka voidaan määrätä translate(x,y)-komennolla ja kuvion koko voidaan määrätä scale(koko)-komennolla. Tärkeintä on lopuksi siirtää origo samassa muodossa takaisin alkuperäiseen paikkaan. Helpoiten tämä onnistuu pushMatrix(); ja popMatrix(); komennoilla. pushMatrix() ottaa koordinaatiston muistiin ja popMatrix() palauttaa muistissa olevan koordinaatiston.
Esimerkki: Ympyrä matematiikan xy-koordinaatistossa
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
void setup () {
size(400,400); // ikkunan koko
background(255); // taustan väri valkea
fill(0); // Musta täyttöväri
}
void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // Peilaa y-koordinaatit
line(-width/2,0,width/2,0); // vaaka-akseli
line(0,height/2,0,-height/2); // pystyakseli
ympyra(100,100,50,"vihreä");
ympyra(-50,150,25,"punainen");
ympyra(-70,-110,80,"keltainen");
}
void ympyra(int x,int y,int r, String vari) {
if (vari == "valkea") {
fill(255,255,255);
} else if (vari == "musta") {
fill(0,0,0);
} else if (vari == "harmaa") {
fill(128,128,128);
} else if (vari == "punainen") {
fill(255,0,0);
} else if (vari == "vihreä") {
fill(0,255,0);
} else if (vari == "sininen") {
fill(0,0,255);
} else if (vari == "keltainen") {
fill(255,255,0);
} else if (vari == "syaani") {
fill(0,255,255);
} else if (vari == "magneta") {
fill(255,0,255);
}
ellipse(x,y,2*r,2*r);
fill(0); // Värin nollaus
}
Kuten huomasit, niin aliohjelmaan voidaan myös välittää merkkijono-tyyppistä tietoa. Kun välität merkkijono tyyppistä tietoa, niin laita välitettävä tieto lainausmerkkien (" ") väliin. Ohjelman tulostus on seuraava.

Matematiikan xy-koordinaatisto luodaan komennoilla translate(width/2,height/2) ja scale(1,-1); Komento: translate(width/2,height/2); siirtää origon ikkunan keskelle ja komento: scale(1,-1);peilaa y-koordinaatin arvot eli y kasvaa ylöspäin. x- ja y-akselit on hyvä myös tulostaa. Ne saat tulostettua line()-komennolla, jossa on käytetty komentoja width ja height funktion parametreina. Tämä on järkevää, koska silloin xy- koordinaatisto saadaan aina ikkunan keskelle riippumatta siitä mikä on ikkunan koko.
Esimerkki: Naama
Kuinka piirtäisit kuvan mukaisen naaman? Origo on ikkunan keskellä. Seuraavilla komennoilla saataisiin naama aikaiseksi.
fill(200,100,50); // Ruskea väri
ellipse(0,0,200,200); // Taakse tuleva ympyrä
fill(100,200,200); // Sininen väri
ellipse(-25,-25,40,80); // Vasen silmä
ellipse(25,-25,40,80); // Oikea Silmä
fill(0); // Musta väri
ellipse(-25,0,20,20); // Silmän mustuainen, vasen
ellipse(25,0,20,20); // Silmän mustuainen, oikea
fill(255,0,0); // Punainen väri
arc(0,50,100,50,radians(0),radians(180),PIE); // Suu
Mietitään seuraavaksi, kuinka tästä kannattaa tehdä aliohjelma. Kaikkein järkevin tapa on käyttää aliohjelmassa translate(x,y) ja scale(r); komentoja. Jolloin pääohjelma ja aliohjelma on seuraavanlaiset.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
void setup() {
size(400, 400); // Ikkunan koko
background(255); // Taustaväri valkoinen
}
void draw() {
for (int a=50; a <= 350; a=a+50) {
// a saa arvoja 50,100,150,200,250,300,350
naama(a,50,50); // Ylärivi, Huomaa x-koordinaatissa muuttuja a
naama(a,150,100); // Keskellä
naama(a,300,150); // Alarivi
}
}
void naama(int x, int y, int w) {
pushMatrix(); // Koordinaatisto muistiin
translate(x, y); // Siirrä hahmoa x:n verran oikealla ja y:n verran alas
scale(w/200.0); // Skaalaa kuvio isommaksi tai pienemmäksi
fill(200,100,50); // Ruskea väri
ellipse(0,0,200,200); // Taakse tuleva ympyrä
fill(100,200,200); // Sininen väri
ellipse(-25,-25,40,80); // Vasen silmä
ellipse(25,-25,40,80); // Oikea Silmä
fill(0); // Musta väri
ellipse(-25,0,20,20); // Silmän mustuainen, vasen
ellipse(25,0,20,20); // Silmän mustuainen, oikea
fill(255,0,0); // Punainen väri
arc(0,50,100,50,radians(0),radians(180),PIE); // Suu
popMatrix(); // Palauta muistissa oleva koordinaatisto
}
Kun ohjelma ajetaan, se tulostaa seuraavaa.

Kuten huomasit, lisäämällä pääohjelmaan for-silmukka, aliohjelmaa voidaan kutsua useasti.
Muutetaan pääohjelmassa koodi seuraavasti.
|
void draw() {
translate(200,200);
for (int a=0; a <= 12; a++) { // a = 0,1,2,3,4,5,6,7,8,9,10,11,12
rotate(radians(30)); // Pyöritä 30° myötäpäivään
naama(100,0,50); // Aliohjelman kutsu
}
}
Tulostuu 12 kappaletta naamoja ympyrän kehälle.

Kuinka naamat saataisiin spiraalille? Muutetaan pääohjelma seuraavanlaiseksi.
|
void draw() {
translate(200,200); // Origo ikkunan keskelle
for (int a=0; a <= 360; a=a+10) { // a = 0,10,20,30,...360
rotate(radians(30)); // Pyöritä 30 myötäpäivään
naama(a,0,a); // Aliohjelma kutsu
}
}
Naama menee kohti ulkoreunaa ja samalla koko kasvaa.

Aliohjelmaa voidaan myös ohjata hiirellä. Tehdään seuraava muutos pääohjelmassa olevaan koodiin.
void draw() {
naama(mouseX,mouseY,100);
}
Tällöin ohjelma tulostaa seuraavaa, kun liikutat hiirtä ikkunassa:


