Skip to content

Latest commit

 

History

History
450 lines (409 loc) · 14 KB

funktio.org

File metadata and controls

450 lines (409 loc) · 14 KB

Funktio

Funktiot setup() ja draw()

Ennen kuin ryhdymme määrittelemään funktioita ja piirtämään animaatioita, meidän täytyy tutustua Processing-ohjelmoinnin funktioihin setup() ja draw(). Kun kirjoitetaan Processing-ohjelmia, jotka toimivat ns. aktiivisessa tilassa

  • funktion setup() sisällä tehdään valmistelevat toimenpiteet, kuten piirtoikkunan koon asettaminen
  • funktion draw() sisällä piirretään.

Seuraava esimerkki havainnollistaa näiden funktioiden käyttämistä.

void setup ()
{
  // alustavat toimenpiteet
  size (400, 400); // asetetaan ikkunan koko
  noLoop (); // ei piirretä animaatioita (vielä)
}

void draw ()
{
  // piirtäminen
  rect (200, 100, 150, 50);
}

Jos halutaan kirjoittaa omia funktioita tai piirtää animaatioita, täytyy käyttää Processing-kielen funktioita setup() ja draw(). Ensimmäisessä tehdään alustavat toimenpiteet, toisessa piirretään. Jos ei piirretä animaatioita, funktiossa setup() kannattaa viimeisenä antaa komento noLoop(), joka keventää tietokoneen kuormaa.

Funktio

Kaikki aiemmissa esimerkeissämme käytetyt piirtokomennot kuten size() ja rect() ovat Processing-ohjelmointikielen funktioita. Kohdat, joissa funktiota käytetään ohjelmassa ovat funktiokutsuja. Funktioita on valmiina suuri joukko, ja ohjelmoija voi kirjoittaa niitä lisää.

Edellisessä esimerkissä on määritelty funktio setup(). Katsotaanpa tarkemmin, mistä funktion määrittely koostuu.

void setup ()
{
  size (400, 400);
  noLoop ();
}

Kaikkein mystisin on ensimmäinen rivi. \[ \underbrace{\texttt{void}}_\text{paluuarvo “tyhjä”} \overbrace{\texttt{setup}}^\text{funktion nimi} \underbrace{\texttt{()}}_\text{ei parametreja} \] Ensimmäinen rivi kertoo, että

  • funktio ei anna tuloksena lukua tms. eli paluuarvo on tyhjä: englannin kielen sana void tarkoittaa tyhjää
  • funktion nimi on setup
  • funktio ei tarvitse mitään lisätietoja eli parametreja toimiakseen: sulkujen sisällä ei ole mitään.

Jokaisella funktiolla on nimi. Funktiolla voi olla lisäksi

  • paluuarvo eli luku tms. jonka funktio antaa tuloksena
  • parametreja eli lähtötietoja, jotka funktio tarvitsee toimiakseen; esimerkiksi funktio size() tarvitsee parametreina piirtoikkunan leveyden ja korkeuden.

Ensimmäisen rivin jälkeinen osa on funktion runko, joka kirjoitetaan lauselohkon sisään.

{
  size (400, 400);
}

Funktion määrittelyn osat

Funktion määrittelyssä on seuraavat osat:

paluuarvon_tyyppi nimi (parametrit)
{
  funktion runko
}
  

Tässä kappaleessa funktioilla ei ole paluuarvoa, eli paluuarvon tyyppi on aina void.

{{{example}}}

Piirretään alla oleva kuva, jossa on päällekkäisiä ympyröitä eri kohdissa piirtoikkunaa.

void setup ()
{
  size (400, 400);
  noLoop ();
}

// funktiolla ei paluuarvoa, parametreina kaksi liukulukua
void piirraYmpyraPari (float x, float y)
{
  final float HALKAISIJA = 30; // kunkin ympyrän halkaisija
  final float SADE = HALKAISIJA / 2.0; // kunkin ympyrän säde
  ellipse (x, y - SADE, HALKAISIJA, HALKAISIJA); // ylempi ympyrä
  ellipse (x, y + SADE, HALKAISIJA, HALKAISIJA); // alempi ympyrä
}

void draw ()
{
  // voimme käyttää määrittelemäämme funktiota piirtämisessä
  piirraYmpyraPari (100, 150); // ympyräpari kohtaan (100, 150)
  piirraYmpyraPari (200, 100);
  piirraYmpyraPari (300, 190);
}

Koska ympyröiden piirtäminen halutaan tehdä moneen kertaan epäsäännöllisissä kohdissa, sitä varten kannattaa kirjoittaa funktio.

  1. Annetaan funktion nimeksi piirraYmpyraPari.
  2. Funktio tarvitsee kaksi lähtötietoa eli parametria: ympyräparin keskikohdan \(x\)- sekä \(y\)-koordinaatin. Annetaan näille nimiksi x ja y. Molemmat ovat liukulukuja eli tyyppiä float.
  3. Funktio ei anna tuloksena mitään lukua, eli sillä ei ole paluuarvoa. Niinpä paluuarvon tyyppi on void.

Ohjelmakoodi näyttää seuraavalta.

<<funktio-ympyraparit>>

Funktioiden nimet kirjoitetussa tekstissä

Toisinaan funktioiden nimet esitetään tekstissä muodossa piirraYmpyraPari() ilman paluuarvon tai parametrien tyyppejä tai parametrien nimiä. Joskus myös tyypit sekä parametrien nimet mainitaan tyyliin

void piirraYmpyraPari (float x, float y)
  

Muuttujien, vakioiden ja parametrien näkyvyysalue

Mistä tiedetään, etteivät kahdessa eri funktiossa olevat samannimiset muuttujat mene keskenään sekaisin?

Muuttujan näkyvyysalueella tarkoitetaan sitä ohjelman osaa, jossa muuttujaa voidaan käyttää. Muuttujan näkyvyysalue on se lauselohko, jossa muuttuja määritellään, sekä lauselohkon sisällä olevat muut lauselohkot.

Kaikkien lauselohkojen ulkopuolella määritellyt muuttujat ovat ns. globaaleja muuttujia ja näkyvät kaikissa lauselohkoissa.

Samat säännöt pätevät myös vakioille.

Parametrien näkyvyysalue on sen funktio runko, jonka ensimmäisellä rivillä parametrit määritellään.

{{{example}}}

Alla olevassa ohjelmakoodissa on kaksi funktiota, joissa molemmissa määritellään muuttuja n. Kukin muuttuja n näkyy vain oman funktionsa rungossa, joten ne ovat käytännössä kaksi eri muuttujaa. Sama pätee molempien funktioiden parametreihin x ja y.

// tikkataulun halkaisija on globaali vakio, joka näkyy kaikissa
// funktioissa
final float TAULUN_H = 70; 

void setup ()
{
  // alkuasetukset
  size (800, 500);
  colorMode (HSB, 100);
  noStroke (); // ei ääriviivoja
  noLoop ();
}

// piirretään yksittäinen tikkataulu parametreina annettuun kohtaan
void piirraTikkataulu (float x, float y)
{
  final float N = 10; // tikkataulun sisäkkäisten ympyröiden lukumäärä
  final float ASKEL = TAULUN_H / N; // ympyröiden halkaisijoiden ero

  // seuraavaksi piirrettävän ympyrän halkaisija
  float ympyranHalkaisija = TAULUN_H;

  for (int n = 1; n <= N; n++)
  {
    if (n % 2 == 1)
      fill (100);
    else
      fill (0);

    ellipse (x, y, ympyranHalkaisija, ympyranHalkaisija);
    ympyranHalkaisija -= ASKEL;
  }
}

// piirretään lkm tikkataulua siten, että ensimmäisen keskikohta on
// (x, y) ja muut ovat siitä oikealle
void piirraTikkatauluRivi (int lkm, float x, float y)
{
  float kpX = x; // tikkataulun keskipisteen x-koordinaatti

  for (int n = 1; n <= lkm; n++)
  {
    piirraTikkataulu (kpX, y);
    kpX += TAULUN_H;
  }
}

void draw ()
{
  piirraTikkatauluRivi (3, 100, 100);
  piirraTikkatauluRivi (6, 50, 200);
  piirraTikkatauluRivi (4, 350, 300);
  piirraTikkataulu (70, 400);
}

Funktioiden käyttötarkoituksia

Ohjelmoijat käyttävät funktioita mm.

  • usein tarvittujen toimintojen automatisointiin (esim. tikkataulun piirtäminen useaan eri kohtaan tai peräti useassa eri ohjelmassa)
  • ohjelmakoodin selkiyttämiseen (yksittäisen tikkataulun piirtämisen erottaminen tikkataulurivin piirtämisestä).

Tehtävät

  1. Alla on määritelty funktio piirraS(). Kopioi koodi Processing-ohjelmaan ja kirjoita funktio draw(), jossa kutsutaan funktiota piirraS() useaan kertaan, sekä funktio setup(), jossa määritellään piirtoikkunan koko ja kutsutaan funktiota noLoop().
    void piirraS (float x, float y)
    {
      colorMode (HSB, 100);
      final float H = 10, S = H / 2;
      fill (100);
      ellipse (x - S, y, H, H);
      ellipse (x + S, y, H, H);
      fill (0);
      ellipse (x - S, y, S, S);
      ellipse (x + S, y, S, S);
    }
        
  2. Alla olevassa ohjelmassa on virhe, joka johtuu vakion näkyvyysalueesta. Kopioi koodi Processing-ohjelmaan ja korjaa virhe.
    void setup ()
    {
      final float VARISAVY = 20;
    
      size (400, 400);
      colorMode (HSB, 100);
      background (VARISAVY, 100, 100);
      noLoop ();
    }
    
    void draw ()
    {
      fill (VARISAVY + 20, 100, 100);
      rect (100, 100, 100, 100);
    }
        
  3. Määrittele funktio
    void piirraYmpyra (float x, float y)
        

    joka piirtää ympyrän, jonka keskipiste on kohdassa (x, y). Ympyrän halkaisija on 20. Käytä kirjoittamaasi funktiota yhdessä funktioiden setup() ja draw() kanssa alla olevan tyyppisen kuvan piirtämiseen. Voit valita piirtoikkunan koon sekä ympyröiden paikat vapaasti.

    void setup ()
    {
      size (400, 400);
      noLoop ();
    }
    
    void piirraYmpyra (float x, float y)
    {
      final float HALKAISIJA = 20;
      ellipse (x, y, HALKAISIJA, HALKAISIJA);
    }
    
    void draw ()
    {
      piirraYmpyra (40, 90);
      piirraYmpyra (120, 100);
      piirraYmpyra (150, 170);
      piirraYmpyra (350, 300);
    }
    
        
  4. Määrittele funktio
    void piirraNelioPari (float x, float y)
        

    joka piirtää kaksi neliötä vierekkäin siten, että vasemmanpuoleisen neliön vasen yläkulma on kohdassa (x, y). Käytä kirjoittamaasi funktiota yhdessä funktioiden setup() ja draw() kanssa alla olevan tyyppisen kuvan piirtämiseen. Neliön sivun pituus on 20. Muut mitat voit valita vapaasti.

    void setup ()
    {
      size (400, 400);
      noLoop ();
    }
    
    void piirraNelioPari (float x, float y)
    {
      final float SIVU = 20;
      rect (x, y, SIVU, SIVU);
      rect (x + SIVU, y, SIVU, SIVU);
    }
    
    void draw ()
    {
      piirraNelioPari (50, 100);
      piirraNelioPari (300, 30);
      piirraNelioPari (250, 270);
    }
        
  5. Määrittele funktio
    void piirraRasti (float x, float y, float varisavy)
        

    joka piirtää rastin kohtaan (x, y) käyttämällä värisävyä varisavy. Jos rastin keskikohta on pisteessä (x, y), niin vasen yläkulma on kohdassa (x - 10, y - 10). Piirrä funktion avulla alla olevan kaltainen kuva, jossa on erivärisiä rasteja mustalla taustalla.

    void setup ()
    {
      size (400, 400);
      colorMode (HSB, 100);
      background (0);
      noLoop ();
    }
    
    void piirraRasti (float x, float y, float varisavy)
    {
      final float S = 10;
      stroke (varisavy, 100, 100);
      line (x - S, y - S, x + S, y + S);
      line (x - S, y + S, x + S, y - S);
    }
    
    void draw ()
    {
      piirraRasti (30, 50, 0);
      piirraRasti (300, 350, 17);
      piirraRasti (70, 200, 62);
      piirraRasti (300, 50, 35);
    }
        
  6. Alla olevan ohjelman pitäisi piirtää viisi pystyriviä ympyröitä, mutta pystyrivejä piirretäänkin vain yksi. Kopioi koodi Processing-ohjelmaan ja korjaa virhe.
    int n;
    
    void setup ()
    {
      size (400, 400);
      noLoop ();
    }
    
    void draw ()
    {
      for (n = 1; n <= 5; n++)
        piirraPystyrivi (n * 20);
    }
    
    void piirraPystyrivi (float x)
    {
      final float HALKAISIJA = 10;
      for (n = 1; n <= 10; n++)
        ellipse (x, n * HALKAISIJA, HALKAISIJA, HALKAISIJA);
    }
        

Ratkaisuja

  1. void setup ()
    {
      size (600, 400);
      noLoop ();
    }
    
    <<funktio-silmat>>
    
    void draw ()
    {
      piirraS (50, 50);
      piirraS (400, 100);
      piirraS (300, 200);
    }
        
  2. Vakio VARISAVY täytyy siirtää globaaliksi vakioksi, jotta se näkyy molemmissa funktioissa.
    final float VARISAVY = 20;
    
    void setup ()
    {
      size (400, 400);
      colorMode (HSB, 100);
      background (VARISAVY, 100, 100);
      noLoop ();
    }
    
    void draw ()
    {
      fill (VARISAVY + 20, 100, 100);
      rect (100, 100, 100, 100);
    }
        
  3. <<funktio-ympyra>>
        
  4. <<funktio-vierekkaiset-neliot>>
        
  5. <<funktio-rasti>>
        
  6. Muuttuja n täytyy määritellä erikseen funktioissa draw() ja piirraPystyrivi().