Ogni gioco ha bisogno di uno scopo, semplice o complicato che sia, altrimenti non ha senso di esistere. Per approfondire questi aspetti di progettazione, è utile leggere la Guida Game Design.
Poiché non ci basta basta sconfiggere dei temibilissimi ombrellini volanti, introduciamo la possibilità di raccogliere delle monete per accumulare un punteggio e arrivare ad un portale di uscita, che ci permetterà di accedere al livello successivo.
Aggiungiamo quindi "la classe" Coin
per le monete, che in realtà è una function
che eredita da GameObj
:
function Coin(x,y) {
// costruttore
GameObj.call(this, x, y);
// sprite e metodo draw
this.SetSprite(game.sprCoin);
// centra offset dello sprite
this.OffsetCenter();
// ferma l'animazione
this.animSpeed = 0;
this.hit = false;
// variabile per l' ondeggiamento
this.boing = Math.random() * 3;
this.bbox = new BoundingBox(x-this.xOffset, y-this.yOffset,
this.sprite.w, this.sprite.height);
this.Update = function() {
// se la moneta è stata presa, va verso l'alto e svanisce
if(this.hit){
this.y--;
if(this.life-- <= 0) {
this.Destroy();
}
} else {
// la moneta ondeggia nell'aria
this.boing += 0.1;
this.y += Math.cos(this.boing)/7;
if(this.bbox.Collides(game.player.bbox)) {
//se collide col player, inizia a ruotare e va verso l'alto
this.life = 30;
this.hit = true;
this.animSpeed = 0.2;
//aggiunge punteggio
game.score++;
//avvia il suono della moneta raccolta
AudioPlay(game.sndCoin);
}
}
}
}
// eredita da GameObj
Inherit(Coin);
Carichiamo lo sprite della moneta e il suono:
// dentro Game
this.sprCoin = rh.LoadSprite("img/coin.png",4);
// ...
this.sndCoin = rh.LoadSound("audio/coin",["ogg", "mp3"]);
this.sndCoin.volume = 0.03;
Oltre agli ombrelli, nel livello caricato ci sono anche altri oggetti, tra cui le monete.
In LoadLevel
, aggiungiamo un altro case, per istanziare i nostri "Coin":
// dati sugli oggetti
var objects = levels[lev][3];
for(var i = 0; i < objects.length; i++) {
//...
switch(...) {
case "umbrella":
//...
case "coin":
new Coin(x+this.cellSize/2, y+this.cellSize/2);
this.coinsCount++;
break;
}
}
A questo punto, manca solo un portale che ci condurrà al livello successivo. Come al solito, carichiamo l'immagine:
this.sprPortal = rh.LoadSprite("img/portal.png",4);
E definiamo l'oggetto Portal
:
function Portal(x,y) {
// costruttore
GameObj.call(this, x, y);
//imposto sprite e funzione Draw
this.SetSprite(game.sprPortal);
//velocità animazione
this.animSpeed = 0.25;
//offset al centro dello sprite
this.OffsetCenter();
this.bbox = new BoundingBox(x - this.xOffset, y - this.yOffset, this.sprite.w, this.sprite.height);
this.Update = function(){
//se collide con il player, vai al livello successivo
if(this.bbox.Collides(game.player.bbox)){
game.LoadLevel(game.level + 1);
}
}
}
Inherit(Portal);
Dentro LoadLevel
, aggiungiamo un case allo switch
per istanziare il portale d'uscita:
//dati sugli oggetti
//...
for(var i = 0; i < objects.length; i++){
//...
switch(objects[i][2]){
//...
case "end":
new Portal(x, y);
break;
}
}
Allo stesso modo, aggiungiamo il punto di spawn, caricando prima sprite
:
this.sprSpawn = rh.LoadSprite("img/spawn.png",3);
Definiamo l'oggetto Spawn
function Spawn(x,y) {
GameObj.call(this, x, y);
this.SetSprite(game.sprSpawn);
this.animSpeed = 0.25;
}
Inherit(Spawn);
Carichiamolo dentro loadLevel
.
Dentro LoadLevel, aggiungiamo un case allo switch per istanziare il portale d'uscita
// dati sugli oggetti
// ...
for(var i = 0; i < objects.length; i++) {
// ...
switch(objects[i][2]) {
// ...
case "spawn":
//istanzia un oggetto spawn
var spawn = new Spawn(x, y);
//imposta il punto di spawn
this.spawnX = x+this.cellSize/2;
this.spawnY = y+this.cellSize;
break;
}
}
Cambiamo leggermente il codice all'interno dell'oggetto Player
function Player(){
//...
this.xStart = game.spawnX;
this.yStart = game.spawnY;
//...
}
Non proseguiremo oltre nell'espandere il gameplay, anche se si possono aggiungere ancora tantissime cose:
- Nemici che sparano e con comportamenti differenti
- Delle trappole su cui non si può camminare (spuntoni, acido, lava, ecc...)
- Powerup collezionabili nei livelli
- Diversi tipi di sparo
Potete sfruttare l'aggiunta di queste features per fare pratica e completare il gioco.