Close menu
Close menu

Tunnistaudu

Kirjaudu

Etkö ole vielä jäsen?

Liity jäseneksi

Esimerkki peli

Yhdistetään hahmon ohjailu nuolinäppäimillä ja taulukkoidea ja luodaan peli, jossa avaruusalus väistelee putoavia meteoriittejä (ympyröitä). Ympyröillä on paikka (x,y) joiden arvot sijoitamme taulukkoon. Ympyrä sijoitetaan ikkunan yläreunassa taulukkoon ja poistetaan taulukosta ikkunan alareunassa. Ympyrän vaakasuuntainen paikka x arvotaan satunnaisesti ikkunan leveyden mukaan. Ympyrän pystysuuntainen paikka on alussa y = 0, mutta se kasvaa laskurin avulla. Käytänössä jokaisen ympyrän y arvoa taulukossa kasvatetaan laskurin pallot[a].y = pallot[a].y+nopeus avulla, missä a on for-silmukan muuttuja, joka käy läpi taulukon kaikki solut. Kokonainen ohjelma on seuraava.

var paikkax = 200;           // Aluksen vaakasuuntainen paikka alussa
var paikkay = 550;           // Aluksen pystysuuntainen paikka alussa
var koko = 20;               // Aluksen koko
var muutos = 0.2;            // Aluksen nopeus
var pisteet = 0;             // Pisteet alussa
var pallot = [];             // Luodaan pallot taulukko
var r = 10;                  // Meteoriitin (ympyrän) säde
var nopeus = 2;              // Meteoriitin nopeus
function setup() {
  createCanvas(600, 600);                  // Ikkunan koko
  pallot[0] = { x:random(width), y:0 };    // Sijoitetaan ensimmäinen ympyrä taulukkoon 
  textSize(20);                            // Tekstin koko 20
  button = createButton('Uusi peli');      // Luo painonappi button
  button.position(500, 20);                // Painonapin paikka oikean yläreuna eli piste (500,20)
  button.mousePressed(UusiPeli);           // Kun painonappia painetaan, niin kutsu UusiPeli funktiota
}

function draw() {
  background(200,200,0);                       // Tyhjennä tausta
  fill(255,0,0);                               // Aseta punainen täyttöväri ympyrää varten
  
  for (var a=0; a< pallot.length; a++) {       // Käy taulukon solut läpi
    ellipse(pallot[a].x,pallot[a].y,2*r,2*r);  // Piirrä ympyrät, jossa paikka luetaan taulukosta
    pallot[a].y=pallot[a].y+nopeus;            // Kasvata y:n arvoa nopeuden verran (= ympyrä liikkuu alaspäin)
  
    if (pallot[a].y == 50) {                   // 50 px välein
          pallot.push ({                       // Luo uusi ympyrä taulukkoon
            x: random(width),                  // Arvotaan vaakasuuntainen paikka
            y: 0                               // Sijoitetaan ikkunan yläreunaan
          })
         
    }
     if (pallot[a].y > (height+r)) {           // Jos ympyrä saavuttaa alareunan
          pallot.shift();                      // Poista ympyrä taulukosta
          pisteet++;                           // Anna yksi piste, koska väistely on onnistunut
    } 
    
    if (keyIsPressed) {                                                
    // Jos painiketta painettu
     if ((keyCode == LEFT_ARROW) && (paikkax > koko)) {                
    // Jos vasen pohjassa ja ei vielä ikkunan vasemmassa reunassa
      paikkax=paikkax-muutos;                                          
     // Liiku vasemmalle pienentämällä paikkax:n arvoa muutoksen verran
     }                                                                 
     // Lopeta jos
     if ((keyCode == RIGHT_ARROW) && (paikkax < (width-koko))) {       
     // Jos oikea pohjassa ja ei vielä ikkunan oikeassa reunassa
      paikkax=paikkax+muutos;                                          
     // Liiku oikealle kasvattamalla paikkax:n arvoa muutoksen verran
     }                                                                 
     // Lopeta jos
    }                                                                  
    // Lopeta ulompi jos (KeyIsPressed)
    hahmo(paikkax,paikkay,koko/100,0);
    // Jos ympyrä on avaruusaluksen sisällä
    if ( ((pallot[a].x+r) > paikkax) && ((pallot[a].x-r) < (paikkax+koko)) && 
       ((pallot[a].y+r) > paikkay) && ((pallot[a].y-r) < (paikkay+koko)) ) {
      noLoop();                            // Niin lopeta peli lopettamalla toisto draw-lohkosta
    }
  }
  fill(0);                                 // Tekstin väri musta
  text("Pisteet: "+pisteet,10,50);         // Näytä pisteet
}

function hahmo(x, y, koko,kulma) {
  var w = 150;  // Pyöritys pisteen korjaus
  var h = 150;
  push();         // Koordinaatisto muistiin
  translate(x,y); // Liikuta hahmoa
  rotate(radians(kulma)); // Pyöritä hahmoa
  scale(koko);    // Skaalaa hahmoa
  // Tästä alkaa oman hahmon piirtokomennot

  strokeWeight(3);
  fill(200,50,0);
  rect(70-w,130-h,20,100);
  rect(210-w,130-h,20,100);
  rect(110-w,200-h,80,40);
  fill(250,100,0);
  triangle(150-w,100-h,50-w,200-h,250-w,200-h);
  fill(180,80,0);
  beginShape();
   vertex(150-w,50-h);
   vertex(170-w,100-h);
   vertex(200-w,220-h);
   vertex(100-w,220-h);
   vertex(130-w,100-h);
  endShape(CLOSE);
  fill(255,255,0);
  ellipse(150-w,125-h,40,50);

  // Tähän loppuu oman hahmon piirtokomennot
  pop();
}

function UusiPeli() {
  pallot = [];
  pallot[0] = { x:random(width), y:0 };
  paikkax = 200;
  paikkay = 550;
  pisteet = 0;
  loop();
}


Voit testa peliä tässä. Avaruusalus liikkuu vasemmalle ja oikealle nuolinäppäimillä. Jos peli ei tottele nuolinäppäimiä, niin voit aluksi napsauttaa pelin päällä hiiren vasemmalla painikkeella, jotta ikkuna on valittu. Huomaa, että tätä peliä ei voi ohjata tabletilla.

Paranneltu peli

Parannetaan peliä vielä siten, että alus voi ampua (neliöitä). Ammuksia varten tarvitsemme toisen taulukon, johon ammukset sijoitetaan ja josta ne poistetaan. Lisäksi tarvitsemme ehdon, että onko ympyrä (= meteoriitti) neliön (=ammus) sisäpuolella. Jos on niin siinä tapauksessa poistamme ympyrän taulukosta eli taulukon keskeltä. Poisto taulukon keskeltä onnistuu splice-komennolla. Katsotaan koodia tarkemmin.

var paikkax = 200;    // Aluksen aloituspaikka vaakasuunnassa
var paikkay = 550;    // Aluksen aloituspaikka pystysuunnassa
var koko = 20;        // Aluksen koko
var muutos = 0.2;     // Aluksen nopeus
var pisteet = 0;      // Pisteet alussa
var ammuttu = false;  // Ei vielä ammuttu, muuttuja estää sarjatulen
var laskuri = 0;      // Laskuri-muuttuja meteoriitteja varten, jotka luodaan laskurin avulla
var pallot = [];      // Luodaan pallot-taulukko (=meteoriitit)
var ammukset = [];    // Luodaan ammukset-taulukko (=ammukset)
var r = 10;           // Ympyrän säde
var r2 = 20;          // Neliön koko
var nopeus = 2;       // Meteoriitin (Ympyrän) nopeus
var nopeus2 = 5;      // Ammuksen (Neliön) nopeus

function setup() {
  createCanvas(600, 600);                // Ikkunan koko 600x600
  pallot[0] = { x:random(width), y:0 };  // Sijoitetaan ensimmäinen ympyrä taulukkoo
  textSize(20);                          // Tekstin koko 20
  button = createButton('Uusi peli');    // Luodaan painonappi
  button.position(500, 20);              // painonapin paikka
  button.mousePressed(UusiPeli);         // Kun painonappia painetaan, niin kutsutaan funktiota UusiPeli
}

function draw() {                        
  laskuri++;                             // Kasvata laskuria
  if (laskuri%50 == 0) {                 // Kun laskuri saa arvoja 50,100,150,200,250,... jne
          pallot.push ({                 // niin luodaan uusi ympyrä
            x: random(width),            // Arvotaan vaakasuuntainen paikka
            y: 0                         // Sijoitetaan ikkunan yläreunaan
          });
  }
  background(200,200,0);                           // Tyhjennä ikkuna
  fill(255,0,0);                                   // Punainen täyttöväri
  
  for (var a = (pallot.length-1); a >= 0; a--) {   // Käydään pallo-taulukko läpi lopusta alkuun
    ellipse(pallot[a].x, pallot[a].y ,2*r,2*r);    // Piirrä ympyrät
    pallot[a].y=pallot[a].y+nopeus;                // Liikuta ympyröitä alaspäin kasvattamalla y:n arvoa taulukossa
     if (pallot[a].y > (height+r)) {               // Jos ympyrä on ikkunan alareunassa
          pallot.shift();                          // niin poista ympyrä taulukosta
          pisteet++;                               // Anna piste lisää koska olet väistellyt onnistuneesti
    } 
    // Avaruusaluksen ohjaus rakenne
    if (keyIsPressed) {                                            
    // Jos näppäintä painettu
     if ((keyCode == LEFT_ARROW) && (paikkax > koko)) {            
     // Jos vasemmalle painettu ja ei olla vielä reunassa
      paikkax=paikkax-muutos;                                      
     // Liikuta avaruusalusta vasemmalle laskurin avulla
     }                                                             
     // Lopeta jos
     if ((keyCode == RIGHT_ARROW) && (paikkax < (width-koko))) {   
     // Jos oikealle painettu ja ei olla vielä reunassa
      paikkax=paikkax+muutos;                                      
     // Liikuta avaruusalusta oikealle laskurin avulla
     }                                                             
     // Lopeta jos
     if (key == char(32))  {                                       
     // Jos painettu välilyönti painiketta
       if (ammuttu == false) {                                     
      // Eikä vielä ammuttu
         ammukset.push ({                                          
      // Niin silloin luo neliö ammukset-taulukkoon
           x2: paikkax-10,                                         
       // Ammuksen aloituspaikka avaruusaluksen mukaan
           y2: paikkay-30                                          
       // Ammuksen aloituspaikka avaruusaluksen mukaan
         });
         ammuttu = true;                                           
       // Muuta arvo ammuttu eli voi ampua uudestaan
       }                                                           
       // ennen kuin on vapauttanut painalluksen
      }
    } else {                                                       
       // Jos ei painike ole pohjassa
         ammuttu = false;                                          
       // niin anna lupa ampua uudestaan
    }
    hahmo(paikkax,paikkay,koko/100,0);                             
    // Piirrä avaruusalus paikkaan (paikkax, piakkay)
   
    // Tarkistetaab onko meteoriitti osunut avaruusalukseen
    if ( ((pallot[a].x+r) > paikkax) && ((pallot[a].x-r) < (paikkax+koko)) && ((pallot[a].y+r) > paikkay) 
       && ((pallot[a].y-r) < (paikkay+koko)) ) {
      noLoop();                          // Lopeta toisto 
      textSize(100);                     // Tekstin koko
      fill(255,0,255);                   // Tekstin väri
      text("Game Over",50,height/2);     // Tulosta teksti: Game Over
    }
    
   // Tarkistetaan onko meteoriitti osunut ammukseen
   for (var b = (ammukset.length-1); b >= 0; b--) {
     if ( ((pallot[a].x+r) > ammukset[b].x2) && ((pallot[a].x-r) < (ammukset[b].x2+r2)) 
      && ((pallot[a].y+r) > ammukset[b].y2) && ((pallot[a].y-r) < (ammukset[b].y2+r2)) ) {
          pallot.splice(a,1);           // Poista meteoriitti eli ympyrä
          ammukset.splice(b,1);         // Poista ammus eli neliö
          pisteet = pisteet+10;         // Anna 10 pistettä hyvästä osumasta
          background(255);              // Välähdys osumisen merkiksi       
    }  // Lopeta jos
   }  // Lopeta for-silmukka
  }  // Lopeta ulompi for-silmukka
  
  // Ammusten liikkuminen for-silmukan avulla
   for (var c=0; c< ammukset.length; c++) {          // Käydään läpi ammustaulukko läpi
     fill(0,0,255);                                  // Ammuksen väri sininen
     rect(ammukset[c].x2, ammukset[c].y2, r2, r2);   // Piirrä ammukset eli neliöt
     ammukset[c].y2 = ammukset[c].y2 - nopeus2;      // Liikuta ammuksia ylöspäin vähentämällä laskuria
     if (ammukset[c].y2 < 0) {                       // Jos ammus yläreunassa
          ammukset.shift();                          // niin silloin poista ammus
     } // Lopeta jos 
   }  // Lopeta for-silmukka
  
  fill(0);                           // Musta tekstin väri
  textSize(20);                      // Tekstin koko
  text("Pisteet: "+pisteet,10,50);   // Tulosta pisteet
}

function hahmo(x, y, koko,kulma) {
  var w = 150;  // Pyöritys pisteen korjaus
  var h = 150;
  push();         // Koordinaatisto muistiin
  translate(x,y); // Liikuta hahmoa
  rotate(radians(kulma)); // Pyöritä hahmoa
  scale(koko);    // Skaalaa hahmoa
  // Tästä alkaa oman hahmon piirtokomennot

  strokeWeight(3);
  fill(200,50,0);
  rect(70-w,130-h,20,100);
  rect(210-w,130-h,20,100);
  rect(110-w,200-h,80,40);
  fill(250,100,0);
  triangle(150-w,100-h,50-w,200-h,250-w,200-h);
  fill(180,80,0);
  beginShape();
   vertex(150-w,50-h);
   vertex(170-w,100-h);
   vertex(200-w,220-h);
   vertex(100-w,220-h);
   vertex(130-w,100-h);
  endShape(CLOSE);
  fill(255,255,0);
  ellipse(150-w,125-h,40,50);

  // Tähän loppuu oman hahmon piirtokomennot
  pop();
}

function UusiPeli() {
  pallot = [];
  ammukset = [];
  pallot[0] = { x:random(width), y:0 };
  paikkax = 200;
  paikkay = 550;
  pisteet = 0;
  loop();
}

Valmis peli näyttää tältä. Myös tässä napsauta kerran hiirellä ikkunan päällä, ennen kuin ohjata alusta nuolinäppäimillä. Avaruusalus ampuu neliöitä, kun painat nuolinäppäintä.

P5.JS YouTube-kurssi

Haluatko oppia p5.js ohjelmointia lisää? Coding Train on tehnyt YouTube-soittolistan, jossa on kokonainen kurssi P5.js-ohjelmoinnista.
https://www.youtube.com/playlist?list=PLRqwX-V7Uu6Zy51Q-x9tMWIv9cueOFTFA

Kirjastojen käyttö

Mikäli sinua kiinnostaa peliohjelmointi, niin siinä tapauksessa kanttaa tutustua seuraaviin JavaScript-kirjastoihin.

Kirjastoissa on valmiit toiminnot hahmojen liikkumiseen ja animointiin. Lisätietoja kirjastojen käytöstä ja niillä luoduista peleistä on löydettävissä myös YouTubesta. Kokosin tähän muutamia linkkejä. YouTubesta löytyy paljon ohjeita myös p5.js ohjelmointiin.