6.1 Laskuri
Yhteenveto
Esimerkiksi laskuri a++; tarkoittaa laskusääntöä a = a + 1; ja laskuri b--; tarkoittaa laskusääntöä b = b - 1; Laskurin määrittely ja alkuarvo laitetaan heti ohjelman alkuun. Itse laskuri sijoitetaan aina void draw ()-lohkoon, koska void draw ()-lohko on ikuisessa silmukassa ja siksi laskuri kasvaa koko ajan.
Esimerkki, jossa tulostetaan laskurien arvoja.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int a = 0; // Laskurin a alkuarvo
int b = 10; // Laskurin b alkuarvo
void setup() {
size(400,200); // Ikkunan koko
background(255); // Taustaväri valkoinen
fill(0); // Tekstin väri musta
textSize(20); // Tekstin koko 20
}
void draw () {
a++; // a = 1,2,3,4,5,...
text(a,30*a,50); // Tulosta a:n arvo
if (b > 0) { // Jos b on suurempi kuin nolla, niin
text(b,300-30*b,100); // Tulosta b:n arvo
}
b--; // b = 9,8,7,6,5,...
}
Esimerkki, jossa piirretään ympyröitä eri paikkaan.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int a = 0; // Laskurin alkuarvo
void setup() {
size(400,400); // Ikkunan koko
background(255); // Taustaväri valkoinen
fill(255,0,0); // Täyttöväri punainen
}
void draw () {
translate(200,200); // Orogo ikkunan keskelle
rotate(radians(a)); // Kierrä koordinaatiostoa laskurin arvon verran
a = a + 90; // a = 90,120,180,270,360,...
ellipse(100,0,100,100); // Piirrä ympyrä
}
Laskuri
Laskuri tarkoittaa yksinkertaista laskutoimitusta kokonaislukumuuttujilla, jossa muuttujan uusi arvo on sama kuin muuttujan vanha arvo lisättynä muutos. Jos esimerkiksi muutos on 1, niin laskuri voidaan kirjoittaa muodossa:
muuttuja = muuttuja + 1;
Tämä voidaan merkitä ohjelmointikielessä lyhemminkin muodossa:
muuttuja++;
Ennen kuin voit käyttää laskuria, niin se on määriteltävä laskuri joko kokonaisluku tai desimaaliluku muuttujaksi. Samalla kun määrittelet laskuri-muuttujan, niin anna laskurille alkuarvo. Laskurimuuttuja määritellään seuraavasti:
int muuttuja = 0;
Koska a:n alkuarvo on 0, niin tässä muuttuja a saa arvoja: 0, 1, 2, 3, 4, 5, 6,… Laskuri-muuttujan määrittely ja muuttujan alkuarvon asettaminen on tehtävä heti ohjelman alussa eli laskuri-muuttujan pitää olla ns. globaali muuttuja.
Katsotaan yksikertaisella esimerkillä mitä tapahtuu, kun laskuri lisätään void draw () silmukassa olevaan piirtokomentoon.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int a = 0; // Laskuri-muuttujan alkuarvo
void setup () {
size(400,200); // Ikkunan koko
background(255); // Taustaväri valkoinen
fill(255,0,0); // Täyttöväri punainen
}
void draw () {
a = a + 1; // Laskuri kasvaa yhdellä
ellipse(a,100,100,100); // Piirretään ellipsi
}
Havaitsemme, että punainen ympyrä lähtee liikkumaan oikealle. Kun laskurimuuttuja kasvaa, niin samalla kasvaa ympyrän x-koordinaatti. Kun koodia katsotaan tarkemmin, niin laskuri muuttuja on määritelty heti ohjelman alussa. Miksi sitä ei voi määritellä void draw () – lohkossa? Syy on alkuarvon asettamisessa. Jos laskurimuuttujalle määriteltäisiin alkuarvo void draw ()-lohkossa, niin laskuri nollautuisi koko ajan ja ympyrä ei liikkuisi mihinkään, koska laskeminen lähtisi koko ajan aina alusta.
Itse laskutoimitus: a = a +1; pitää määritellä void draw() – lohkossa, koska void draw ()-lohko on ikuisessa silmukassa. Silmukan ajaminen tarkoittaa laskurin kasvamista. Jos haluat, että ympyrä liikkuu nopeammin, niin voit laittaa muutoksen suuremmaksi kuin 1 eli kirjoittaa laskurin esimerkiksi muodossa: a = a + 2;
Alla on esitetty kuva ohjelman suorituksesta.
Muutetaan koodia. Mitä tapahtuu, jos ympyrä piirretään komennolla: ellipse(200,200,a,a); ?
Kuviota voi myös liikutella translate(x,y) komennolla. Muuta edellinen esimerkki tällöin muotoon.
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int a = 0; // Laskuri-muuttujan alkuarvo
void setup () {
size(400,200); // Ikkunan koko
background(255); // Taustaväri valkoinen
fill(255,0,0); // Täyttöväri punainen
}
void draw () {
a = a + 1; // Laskuri kasvaa yhdellä
pushMatrix(); // Ota koordinaatisto muistiin
translate(a,100); // Liikuta koordinaatistoa
ellipse(0,0,100,100); // Piirretään ympyrä paikkaan (0,0)
popMatrix(); // Palauta koordinaatisto muistista
}
Kuinka ympyrä saataisiin liikkumaan vasemmalle? Vasemmalle liike onnistuu yksikertaisesti vähentämällä lukuja. Muutetaan koodia ja katsotaan käytännössä.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int a = 0; // Laskuri muuttujan alkuarvo
void setup () {
size(400,200); // Ikkunan koko
background(255); // Taustaväri valkoinen
fill(255,0,0); // Täyttöväri punainen
}
void draw () {
a = a - 1; // Laskuri pienenee yhdellä
ellipse(400+a,100,100,100); // Huomaa: ympyrä alussa oikealla
}
Kirjoitamme laskurin nyt muodossa: a = a – 1; Lisäksi ympyrä pitää siirtää alussa oikealle, siksi ympyrän x:n arvoon on lisätty 400. Nyt laskuri a saa arvoja: 0, -1, -2, -3, -4,… ja x:koordinaatti arvoja: 400, 399, 398, 397, 396,…

Muuta koodia. Mitä tapahtuu, jos ympyrä piirretään komennolla: ellipse(200,200-a,100,100); ? Kokeile muuttaa background(255); komento heti void draw ()-lohkon alkuun, mitä tapahtui?
Ohjelmoinnissa on määritelty laskureita seuraavalla tavalla. Esimerkiksi tässä laskurimuuttujana käytetään a-kirjainta, joka on määritelty kokonaisluvuksi.
| Laskuri | Lyhyemmin | Merkitys |
|---|---|---|
| a = a + 1; | a++; | Kasvattaa laskuria yhdellä |
| a = a - 1; | a--; | Vähentää laskuria yhdellä |
| a = a + 2; | a += 2; | Kasvattaa laskuria kahdella |
| a = a - 2; | a -= 2; | Vähentää laskuria kahdella |
| a = a*2; | a *= 2; | Kertoo laskurin kahdella |
| a = a/2; | a /= 2; | Jakaa laskurin kahdella |
Esimerkki:
a) Jos laskuri on a = a + 3; ja a:n alkuarvo 5, niin a saa tällöin arvoja: 5, 8, 11, 14, 17,...
b) Jos laskuri on a = a - 2; ja a:n alkuarvo on 3, niin a saa tällöin arvoja: 3, 1, -1, -3, -5, -7,...
c) Jos laskuri on a =a*2; ja a:n alkuarvo on 1, niin a saa tällöin arvoja: 1, 2, 4, 8, 16, 32,...
d) Jos laskuri on a=a/2; ja a:n alkuarvo on 4, niin a saa tällöin arvoja: 4, 2, 1, 0.5, 0.25, 0.125,...
Esimerkki: Kuvion liikuttelu reittiä pitkin

Haluamme liikuttaa ympyrän pisteestä A(100,100) pisteeseen B(300,200) siten, että kuljemme ensin 200 askelta oikealle ja 100 askelta alaspäin. Kuinka se onnistuu?
Ensinnäkin tarvitsemme kaksi laskuria, toinen pystysuuntaa varten ja toinen vaakasuuntaa varten. Toiseksi tarvitsemme if-lauseita, joilla pysäyttää laskuri tarvittaessa. Tehdään seuraava ohjelma.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int a = 0; // Laskuri vaakasuuntaa varten
int b = 0; // Laskuri pystysuuntaa varten
void setup () {
size(400,400); // Ikkunan koko
fill(255,0,0); // Punainen täyttöväri
background(255); // Valkea taustanväri
}
void draw () {
if (a <= 200) { // Jos on kuljettu 200 tai alle, niin
a++; // Kasvata laskuria vaakasuunnassa
ellipse(100+a,100+b,10,10); // Liiku oikealle
}
else { // Jos ehto ei täyty enää, niin lähde alaspäin
if (b <=100) { // Jos on kuljettu 100 tai alle, niin
b++; // Kasvata laskuria pystysuunnassa
ellipse(100+a,100+b,10,10); // Liiku alaspäin.
}
}
}
Näet, kuinka ympyrä kulkee reitin. Koska laitoimme laskurin if-lauseen sisään, niin laskuria ei enää kasvateta, kun ehto täyttyy. Alla on esitetty ohjelman esimerkkiajo.

Kuinka muuttaisit koodia, jos ympyrä tulisi takaisin loppupisteestä alkupisteeseen?
Esimerkki: Reunasta pomppaaminen
Tehdään ohjelma, jossa pallo liikkuu oikealle ja vasemmalle. Kun ikkunan reuna tulee vastaan, pallo vaihtaa suuntaa.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int a = 0; // Laskurin alkuarvo
boolean suunta = true; // Suunta alussa oikealle
void setup () {
size(400,400); // ikkunan koko
stroke(0); // Musta viivan väri
fill(255,0,0); // Punainen täyttöväri
frameRate(1000); // draw void () lohkon päivityksiä sekunnissa
}
void draw() {
translate(200,200); // Origo (0,0) ikkunan keskelle
background(255); // Tyhjennä tausta
if (suunta == true) { // Jos mennään oikealle
a++; // niin kasvata laskuria
}
if (suunta == false) { // Jos mennään vasemalle
a--; // niin pienennä laskuria
}
if (a > 190) { // Jos tulee oikea reuna vastaan
suunta = false; // niin käännä suunta vasemmalle
}
if (a < -190) { // Jos tulee vasen reuna vastaan
suunta = true; // niin käännä suunta oikealle
}
ellipse(a,0,20,20);
}
Tässä ohjelmassa on myös komento nimeltään frameRate(lukuarvo);. Se kertoo, kuinka monta kertaa sekunnissa void draw ()-lohkoa päivitetään, eli mitä isompi luku, niin sitä nopeammin pallo liikkuu ruudulla. Arvoa ei voi kasvattaa loputtomasti vaan jossain vaiheessa tietokonelaitteiston päivitysnopeus tulee vastaan, jota ei voi ylittää. Oletuksena on 60 päivitystä sekunnissa. Alla on esimerkki ohjelman suorituksesta. Huomaa, että komento background() on siirretty void draw()-lohkoon, niin se siivoaa edelliset pallon jäljet pois. If-lauseilla pallo saadaan myös pomppaamaan seinästä poispäin. Tarvitset kaksi muuttujaa. Toinen muuttujista huolehtii laskurista eli liikkeestä (muuttuja: a) ja toinen suunnasta (muuttuja: suunta). Silloin kun suunta on oikealle (true), niin kasvata laskuria ja vastaavasti silloin kun suunta on vasemmalle (false), niin vähennä laskuria. Kun laskuri on tarpeeksi iso eli pallon keskipisteen vaakasuuntainen koordinaatti ylittää tai alittaa määrätyn raja-arvon, niin käännetään suunta päinvastaiseksi. Tässä raja-arvo on 190 tai -190 eli ikkunan reunasta (200) otetaan pois ympyrän säde (10).

Edellisessä esimerkissä boolean-tyyppisellä muuttujalla määrättiin liikesuunta. Kun muuttuja sai arvon true, niin liikuttiin oikealle. Kun muuttuja sai arvon false, liikuttiin vasemmalle. Tehdään vertailun vuoksi ohjelma ilman boolean-muuttujaa. Yksinkertaisesti voimme muuttaa lisäyksen vx merkin päinvastaiseksi, kun kohtaamme ikkunan reunan. Tämä myös muuttaa pallon liikesuunnan.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
float x = 50; // Pallon keskipisteen vaakakoordinaatti
float y = 50; // Pallon keskipisteen pystykoordinaatti
float vx= 2; // Lisäyksen suuruus
float r = 20; // Pallon säde
void setup() {
size(800,600); // Ikkunan koko
fill(0,0,255); // Täyttöväri sininen
smooth(); // Liikeen pehmennys
}
void draw () {
background(255); // Tyhjennä tausta ja väritä se valkoiseksi
ellipse(x,y,2*r,2*r); // Piirrä ympyrä
x = x + vx; // Kasvata x:n arvoa lisäyksen verran
if (x+r>= width) {
// Jos pallon oikea reuna saavuttaa ikkunan oikean reunan, niin
vx = -vx; // muuta lisäys päinvastaiseksi
}
if (x-r <=0) {
// Jos pallon vasen reuna saavuttaa ikkunan vasemman reunan, niin
vx = -vx; // muuta lisäys päinvastaiseksi
}
}
Esimerkki: Kierto ympäri
Palataan edellisen tunnin esimerkkiin. Laskurin käyttäminen lyhentää koodia huomattavasti.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int kulma = 0;
void setup () {
size(400,400); // ikkunan koko
background(255); // Valkea taustaväri
stroke(0); // Musta viivan väri
fill(255,0,0); // Punainen täyttöväri
}
void draw() {
translate(200,200); // Origo (0,0) ikkunan keskelle
kulma=kulma+30; // Kasvata kulmaa 30 asteen välein
rotate(radians(kulma)); // Kierrä 30° myötäpäivään
ellipse(100,0,20,20); // Piirrä ympyrä
}
Koska laskurin avulla kasvatamme kulma-muuttujaa, niin käyttämällä kulma-muuttujaa rotate()-komennon sisällä saamme koordinaatiston pyörimään. Muuttamalla lisäyksen suuruutta, voimme muuttaa ympyröiden määrää. Kokeile muuttaa laskuria ja lopputulos on sen mukainen.
Esimerkki: Pyörivä neliö
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
int a = 0; // Laskurin alkuarvo
void setup () {
size(400,400); // Ikkunan koko
background(0); // Taustaväri musta
strokeWeight(3); // Reunaviivan paksuus 3
noFill(); // Ei täyttöä
}
void draw () {
translate(200,200); // Siirrä origo ikkunan keskelle
rotate(radians(a)); // Pyöritä koordinaatistoa
a = a + 5; // Kasvata laskuria
stroke(random(255),random(255),random(255)); // Arvotaan väri
rect(-100,-100,200,200); // Piirrä neliö ikkunan keskelle
}
Laskurin avulla on helppo luoda taiteellisia efektejä. Tässä esimerkissä siirretään origo ikkunan keskelle, johon on piirretty neliö. Koska laskuri on lisätty rotate()-komentoon, saamme neliön pyörimään. Lisäksi jokaisen neliön reunaviivan väri arvotaan, joka kerta aina erilaiseksi. Lopputulos näyttää tältä:

Jos haluaisit että neliö pyörähtää vain yhden kerran täyden ympyrän verran (360°), niin laskurin ympärille olisi tällöin lisättävä if-lause, joka on muotoa:
if (a <= 360) {
a = a + 5; // Kasvata laskuria
}
Eli kasvata laskuria niin kauan, kunnes a on pienempi tai yhtä suuri kuin 360. Kun a on suurempi kuin 360, ei enää tehdä mitään.
Voit kokeilla muuttaa myös rect()-komennon muotoon:
rect(-random(100),-random(100),random(200),random(200)); Mitä tapahtui?
Esimerkki: Gravitaatio
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
float x = 400; // Pallon alkukoordinaatti vaakasuunnassa
float y = 50; // Pallon alkukoordinaatti pystysuunnassa
float vy = 0; // Laskurin lisäyksen suuruus alussa
float r = 20; // Pallon säde
void setup() {
size(800,600); // Ikkunan koko
fill(0,0,255); // Täyttöväri sininen
smooth(); // Pehmeä liike
}
void draw () {
background(255); // Tyhjennä tausta
ellipse(x,y,2*r,2*r); // piirrä ympyrä muuttujien avulla
y = y + vy; // Kasvata y:n arvoa lisäyksen verran (liike alas/ylös)
vy = vy + 0.1; // Kasvata lisäyksen suuruutta (kiihdytys/jarrutus)
if (y+r >= height) { // Jos saavutetaan alareuna, niin
vy = -vy*0.9; // Muuta lisäys negatiiviseksi
// ja samalla vähennä maksimia 10 %
y = height-r; // Anna y:lle uusi alkuarvo
}
}
Pallon pystysuuntainen paikka on ilmaistu muuttujalla y. Laskurin y = y +vy avulla pallo saadaan liikkumaan. Kun lisäys vy on positiivinen, niin pallo menee alaspäin, koska y:n arvo kasvaa. Kun lisäys vy on negatiivinen, niin pallo menee ylöspäin, koska y:n arvo pienenee. Koska myös muuttujalla vy on oma laskuri eli vy = vy +0.1; niin myös lisäyksen vy suuruus muuttuu. Kun vy on positiivinen, niin lisäys koko ajan kasvaa eli on kiihtyvässä liikkeessä. Kun vy on negatiivinen, niin lisäys koko ajan pienenee eli on hidastuvassa liikkeessä. Hidastuva liike jatkuu, kunnes vy on muuttunut positiiviseksi, jolloin se on taas kiihtyvää liikettä. Kun haluat muuttaa kiihtyvän liikkeen hidastuvaksi, niin sitä varten on ohjelmaan lisättävä ehto eli if-lause. Kun pallon alareuna (y+r) on vähintään yhtä suuri kuin ikkunan korkeus (height), niin tällöin muuta kiihtyvyys hidastuvuudeksi (vy = -vy*0.9). Tähän muutokseen on lisätty kerroin 0.9 eli muutoksesta säilyy vain 90 % jokaisella pompulla, niin pallo ei pääse pomppaamaan enää niin korkealle kuin edellisellä kierroksella. Samalla on hyvä antaa y:lle uusi alkuarvo, niin ei tule pyöristysvirheistä johtuvia heittoja. Oheinen kuva havainnollistaa ohjelman käyttämiä muuttujia.

Lisätään mukaan vielä vaakasuuntainen liike, niin pallo saadaan pomppimaan ikkunan sisällä realistisesti.
|
// Ohjelman tehnyt e-Oppi Oy
// 30.8.2017
float x = 50; // Pallon vaakasuunnan alkuarvo
float y = 50; // Pallon pystysuunnan alkuarvo
float vx= 2; // Vaakasuuntainen nopeus (vakio)
float vy = 0; // Nopeus alussa pystysuunnassa
float r = 20; // pallon säde
void setup() {
size(800,600); // Ikkunan koko
fill(0,0,255); // Täyttöväri sininen eli pallon väri
smooth(); // Pehmeä ruudun päivitys
}
void draw () {
background(255); // Tyhjennä tausta ja väritä se valkoiseksi
ellipse(x,y,2*r,2*r); // Piirrä pallo
x = x + vx; // Liiku vasemalle/oikealle
y = y + vy; // Liiku alas/ylös
vy = vy + 0.1; // Kiihtyvyys/hidastavuus pystyliikeessä
if (y+r >= height) { // Jos ikkunan alareuna saavutettu niin,
vy = -vy*0.9; // muuta kiihtyvyys hidastuvuudeksi ylöspäin
y = height-r; // Anna y:lle uusi alkuarvo (korjaa likiarvon)
}
if (x+r>= width) { // Jos ikkunan oikea reuna saavutettu niin
vx = -vx; // käännä suunta
}
if (x-r <=0) { // Jos ikkunan vasen reuna saavutettu, niin
vx = -vx; // Käännä suunta
}
}
Voit kokeilla muuttaa ikkunan kokoa, muuttujien alkuarvoja tai kertoimia 0.1 ja 0.9 laskukaavoissa. Ohjelmaa voitaisiin kehittää esimerkiksi siten, että arvottaisiin pallon aloituspaikka ja nopeus alussa.


