7.2 Konnagrafiikkaa for-silmukan kanssa

Yhteenveto

  • Tällä tunnilla teemme aluksi jonkin peruskuvion, jota sitten toistamme for-silmukan avulla.
  • Esimerkiksi mieti ensin, kuinka neliö piirretään. Kun jätämme neliön viimeisen kulman vajaaksi täydestä ympyrästä, niin uusi neliö aloitetaan piirtämään eri kulmassa kuin edellinen.
  • Tässä jokainen neliö piirretään 45 astetta eri kulmassa kuin edellinen. Toistettaessa for-silmukkaa 8 kertaa saamme piirrettyä kahdeksan neliötä, kunnes kuvio toistuu alusta.




Koska viimeinen komento on: vasemmalle(45);, niin täysi ympyrä menee 45 astetta yli 360 asteen. Tällöin jokaisen uuden neliön aloituskulma on 45 astetta eri kohdassa kuin edellisen neliön aloituskulma. Nyt neliöt lähtevät kiertymään ympäri. Voit kokeilla muuttaa tätä kulmaa ja toistojen määrää for-silmukassa.

For-silmukka ja aliohjelmat

Palataan viime tunnilla esitettyyn ohjelmaan, jossa määrittelimme funktiot: eteen();, taakse();, oikealle(); ja vasemmalle();. Ohjelma on seuraava.

// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int x = 0; 
int y = 0;
int w = 10; // Kynän paksuus (voit muuttaa)
void setup () {
size(800,800); // Ikkunan koko
background(255); // Taustaväri valkoinen
fill(255,0,0); // Täyttöväri punainen ( voit muuttaa)
noStroke(); // Ei reunaviivaa
noLoop(); // Suoritetaan void draw () lohko kerran
}
void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
eteen(200);
taakse(200);
oikealle(45);
eteen(200);
taakse(200);
}
void eteen(int askel) {
for (int a = 0; a < askel; a++) {
x = x + 1;
ellipse(x,y,w,w);
}
translate(askel,0);
x = 0;
}
void taakse(int askel) {
for (int a = 0; a < askel; a++) {
x = x - 1;
ellipse(x,y,w,w);
}
translate(-askel,0);
x = 0;
}
void vasemmalle(int kulma) {
rotate(radians(kulma));
}
void oikealle(int kulma) {
rotate(radians(-kulma));
}

Katsotaan tarkemmin void draw()-lohkossa olevia komentoja, joilla kutsutaan aliohjelmia.

void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
eteen(200);
taakse(200);
oikealle(45);
eteen(200);
taakse(200);
}

Void draw ()-lohkossa olevilla funktion kutsuilla liikutaan eteenpäin 200 askelta, jonka jälkeen palataan takaisin 200 askelta, jolloin olemme taas lähtöpisteessä. Käännytään oikealle eli myötäpäivään 45 astetta, jonka jälkeen liikutaan taas eteen ja taakse 200 askelta. Lopputulos näyttää nyt tältä.



Jos haluaisimme kiertää täyden ympyrän, niin tällöin funktioiden kutsuja: eteen, taakse ja oikealle, pitäisi tehdä kahdeksan kertaa. Voisiko tämän tehdä lyhyemmin? Muutetaan void draw ()-lohkossa olevaa koodia seuraavasti.

void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
for (int luku=1; luku <= 8; luku++) {
eteen(200);
taakse(200);
oikealle(45);
}
}

Eli lisäämme funktio-kutsujen ympärille for-silmukan, jossa toistetaan kaarisulkeiden välissä olevia komentoja 8-kertaa. Jolloin ohjelma tulostaa seuraavaa.



For-silmukan avulla saamme lyhennettyä koodia huomattavasti. Huomaa, että for-silmukkaa toistettiin eteen, taakse ja oikealle aliohjelmakutsuja kahdeksan kertaa. Koska 8 ∙ 45° = 360°, niin saimme kierrettyä täyden ympyrän for-silmukan avulla.

Entä jos haluaisit piirtää 60 kappaletta erivärisiä viivoja? Muutetaan void draw ()-lohkossa oleva for-silmukka muotoon.

void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
for (int luku=1; luku <= 60; luku++) {
fill(round(random(255)),round(random(255)),round(random(255)));
eteen(200);
taakse(200);
oikealle(6);
}
}

Kun kasvatamme toistojen määrää for-silmukassa, niin viivojen välinen kulma pienenee. Koska 360 : 60 = 6, niin viivojen välinen kulma on nyt 6 astetta. Ohjelma tulostaa nyt seuraavaa.

Ympyrä

Koska for-silmukan avulla saamme nopeasti luotua toistoja, niin voimme helposti piirtää ympyrän seuraavasti. Lisää komento void draw ()-lohkoon.

void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
for (int luku=1; luku <= 360; luku++) {
eteen(1);
oikealle(1);
}
}

Kun mennään eteenpäin yksi askel ja käännytään oikealle yhden asteen verran, niin toistettaessa näitä komentoja 360 kappaletta saamme aikaiseksi ympyrän. Lopputulos näyttää tältä.



Kun muutat eteen(1); komentoon isomman luvun, niin saat aikaiseksi isomman ympyrän. Jos pienennät for-silmukan toistojen määrää, niin saat aikaiseksi kaaren. Kokeile muuttaa arvoja.

Kaksi for-silmukkaa

Lisätään edelliseen esimerkkiin kaksi sisäkkäistä for-silmukkaa. Sisempi silmukka piirtää ympyrän ja ulompi silmukka toistaa sisempää silmukkaa kuusi kertaa, jolloin syntyy kuusi ympyrää. Silmukoiden väliin laitamme komennon oikealle(60), niin aina uuden ympyrän piirtäminen alkaa eri kohdasta, jolloin lopputuloksena on 6 kappaletta päällekkäin meneviä ympyröitä.

void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
for (int luku2=1; luku2 <= 6; luku2++) {
oikealle(60);
for (int luku1=1; luku1 <= 360; luku1++) {
eteen(1);
oikealle(1);
}
}
}

Kun ajat ohjelman, tulostus näyttää nyt tältä.



Huomaa, että laskutoimitukset 60° ∙ 6 = 360° ja 1° ∙ 360 = 360° eli molemmat silmukat kiertävät täyden ympyrän.

Pyörivä neliö

Tehdään jo aikaisemmin tehty pyörivä neliö konnagrafiikalla.

void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
for (int b=1; b <= 30; b++) { // 30 neliötä. b = 1,2,3,...,30
fill(random(255),random(255),random(255)); // Satunnainen väri
translate(-100,100); // Siirrä origo vasemmalle ylös
for (int a=1; a <= 4; a++) { // Yksi neliö = 4 sivua, a = 1,2,3,4
eteen(200);
oikealle(90);
}
translate(100,-100); // Palauta origo neliön keskelle
oikealle(12); // Pyöritä 12° astetta
}
}

Tässä sisemmällä for-silmukalla piirrämme neliön eli toistamme yhtä sivua neljä kertaa. Neliön pyöritys tapahtuu ikkunan keskellä origossa. Ennen piirtämistä siirrämme neliön keskellä olevan origon vasemmalle ylös ja piirtämisen jälkeen palautamme origon neliön keskelle. Nyt tulostuu seuraavaa. Tässä viivan paksuus (w) on pienennetty arvoon 5.

Kukka

Muutetaan void draw()-lohkoon kaksi sisäkkäistä for-silmukkaa.

void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
for (int luku2=1; luku2 <=2; luku2++) {
for (int luku1=1; luku1 <= 15; luku1++) {
eteen(3);
oikealle(6);
}
oikealle(90);
}
}

Jolloin saamme aikaiseksi kukan terälehden. Sisempi silmukka piirtää ympyrän kaaren, jossa keskuskulma on 90 astetta eli 15 ∙ 6° = 90°. Ennen toisen kaaren piirtämistä muutamme suuntaa 90 astetta. Ulompi silmukka käskee piirtämään kaksi kaarta. Kahdesta kaaresta muodostuu kukan terälehden muoto.

Jos haluat pidemmän terälehden, niin silloin kasvata lukuarvoa funktion: eteen(3); kutsussa. Luodaan tästä oma funktio eli lisäämme void draw ()-lohkon alle seuraavan uuden funktion: lehti(pituus);

void lehti(int pituus) {
for (int luku2=1; luku2 <=2; luku2++) {
for (int luku1=1; luku1 <= 15; luku1++) {
eteen(pituus);
oikealle(6);
}
oikealle(90);
}
}

Nyt voimme lyhentää void draw ()-lohkon muotoon.

void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
lehti(3);
}

Tässä muodossa voimme kutsua lehti()-funktiota. Mitä isompi arvo, sitä pidempi lehti piirretään.

Voisimmeko piirtää terälehdistä kukan? Lisätään uusi for-silmukka void draw ()-lohkoon, joka piirtää 10 kappaletta terälehtiä, niin että jokainen uusi terälehti piirretään 36 astetta kierrettynä myötäpäivään, kuin edellinen terälehti. Koska 10 ∙ 36° = 360°, saamme aikaiseksi täyden ympyrän ja kymmenestä terälehdestä muodostuu kukka. Koodi, joka piirtää kukan on seuraava.

void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
for (int luku3 = 1; luku3 <= 10; luku3++) {
lehti(4);
oikealle(36);
}
}

Kukka näyttää nyt tältä.


Voimme jatkaa ideaa eteenpäin eli voimme määritellä funktion: kukka(), joka on seuraavanlainen.

void kukka(int lehtia, int pituus) {
for (int luku3 = 1; luku3 <= lehtia; luku3++) {
lehti(pituus);
oikealle(round(360/lehtia));
}
}

Välitämme kukka()- funktiolle lehtien lukumäärän ja terälehden pituuden. Lehtien lukumäärä vaikuttaa myös siihen kulmaan, jonka arvolla seuraava lehti piirretään. Oikea kulman arvo saadaan selville jakolaskusta, joka on 360 jaettuna lehtien lukumäärä.

Kun kutsut void draw ()-lohkossa kukkaa nyt komennolla, niin lopputulos on esimerkiksi seuraavanlainen.

FunktioLopputulosMerkitys
kukka(8,4); Kukka piirretään 8 lehdellä, jonka pituus on 4.
kukka(12,6); Kukka piirretään 12 lehdellä, jonka pituus on 6.
kukka(5,5); Kukka piirretään 5 lehdellä, jonka pituus on 5.
kukka(3,7); Kukka piirretään 3 lehdellä, jonka pituus on 7.

Lopuksi esitetään vielä kokonainen ohjelma, johon on vielä lisätty ylimääräinen for-silmukka void draw ()-lohkoon. Tämä ylimääräinen silmukka piirtää kuusi kukkaa ympyrän kehälle.

// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int x = 0;
int y = 0;
void setup () {
size(800,800); // Ikkunan koko
background(255); // Taustaväri valkoinen
fill(255,0,0); // Täyttöväri punainen
noStroke(); // Ei reunaviivaa
noLoop(); // Suoritetaan void draw () lohko kerran
}
void draw () {
translate(width/2,height/2); // Origo ikkunan keskelle
scale(1,-1); // xy-koordinaastio peilaamalla y-koordinaatit
for (int luku4 = 1; luku4 <= 6; luku4++) { // Kuusi toistoa
kukka(6,3); // Kukassa kuusi terälehteä, jonka pituus on 3
translate(100,0); // Siirry 100 oikealle
oikealle(60); // Pyöritä koordinaatistoa
}

}

void kukka(int lehtia, int pituus) {
for (int luku3 = 1; luku3 <= lehtia; luku3++) {
lehti(pituus);
oikealle(360/lehtia);
}
}

void lehti(int pituus) {
for (int luku2=1; luku2 <=2; luku2++) {
for (int luku1=1; luku1 <= 15; luku1++) {
eteen(pituus);
oikealle(6);
}
oikealle(90);
}
}
void eteen(int askel) {
for (int a = 0; a < askel; a++) {
x = x + 1;
ellipse(x,y,10,10);
}
translate(askel,0);
x = 0;
}
void taakse(int askel) {
for (int a = 0; a < askel; a++) {
x = x - 1;
ellipse(x,y,10,10);
}
translate(-askel,0);
x = 0;
}
void vasemmalle(int kulma) {
rotate(radians(kulma));
}
void oikealle(int kulma) {
rotate(radians(-kulma));
}

Tulostuu seuraavaa.