Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

GameObject, eventi ed ereditarietà

Creare la struttura degli oggetti fondamentali del gioco, che ci permette di definire, per estensione, tutti gli elementi sullla scena.
Creare la struttura degli oggetti fondamentali del gioco, che ci permette di definire, per estensione, tutti gli elementi sullla scena.
Link copiato negli appunti

I GameObject, sono oggetti generici (function), che possono contenere tutte le informazioni e risorse necessarie agli elementi di gioco. Possono quindi diventare: un personaggio, un nemico, un power-up, una piattaforma, un'interfaccia grafica e ogni elemento del nostro videogame.

Update e Draw

Come accennato nella lezione precedente, il nostro game engine si basa principalmente su un loop che ad ogni frame richiama le funzioni Update e Draw. Possiamo pensare a queste funzioni come agli eventi principali del gioco. Di conseguenza tutti i GameObject dovranno gestire questi eventi con i relativi metodi Update e Draw.

In altre parole si tratta di funzioni comuni a tutti gli elementi del gioco, che ci permettono di gestire in modo generico tutte le istanze, nonostante esse abbiano comportamenti, variabili e funzionalità diverse.

Nella lezione precedente abbiamo anche organizzato la successione degli eventi nel GameLoop, in modo tale che Update sia sempre eseguito prima del Draw. Il motivo è semplice: Update ha il compito di modificare e spostare gli oggetti sulla scena, verificare le collisioni, gestire i frame dell'animazione, etc.

In questo modo, prima dell'esecuzione di Draw, tutte le istanze sono aggiornate, e possono essere disegnate alla posizione corretta, col giusto frame dell'animazione.

Volendo, si possono inserire altri eventi secondari come EndLoop, che viene eseguito dopo il Draw, utilizzato principalmente per aggiornare alcuni GameObject dopo il rendering.

Ereditarietà: creare GameObject simili, ma con una loro identità

La OOP in JavaScript viene implementata in modo diverso da come si fa con altri linguaggi più specifici per la programmazione a oggetti (Java, C#, C++). Non sono infatti presenti le classi, ma si può comunque sfruttare l'ereditarietà prototipale tramite l'oggetto prototype.

>> Leggi di più sulla OOP in JavaScript

Per capirne meglio il funzionamento, creiamo un nuovo file test.html e inseriamo nel tag <script> il seguente codice (oppure utilizziamo la console del browser):

function GameObject(x, y) {
	this.x = x;
	this.y = y;
	this.showInfo = function() {
		alert(this.x + "," + this.y + "," + this.speed);
	}
}

Abbiamo creato una function generale GameObject, che contiene variabili e funzioni che vogliamo ereditare tramite prototype, ecco come:

function Palla(x, y, speed){
	GameObject.call(this, x, y);
	this.speed = speed;
}

In questo script, definiamo una "sotto-classe" Palla, che assume i valori da GameObject.

Alla creazione, utilizziamo il metodo call, per chiamare il constructor di GameObject, utilizzando lo scope dell'istanza corrente (this): se dovessimo generare più istanze di Palla, in questo modo eviteremo di creare variabili e funzioni con la stessa reference che si modificherebbero a vicenda.

>> Leggi di più sulla funzione call

Quindi, tramite prototype, facciamo in modo che Palla erediti la struttura di GameObject, ma che mantenga attivo il suo constructor:

//eredita da GameObject
Palla.prototype = Object.create(GameObject.prototype);
//reimposta il constructor
Palla.prototype.constructor = Palla;
p1 = new Palla(10, 150, 30);
p2 = new Palla(20, 200, 1);
p3 = new Palla(30, 300, 23);
p1.showInfo();
p2.showInfo();
p3.showInfo();

Creiamo quindi varie istanze di Palla, e chiamiamo per ciascuna la funzione showInfo(). Se tutto è andato a buon fine, verranno mostrati 3 messaggi in sequenza, con i seguenti risultati:

10,150,30
20,200,1
30,300,23

Un utilizzo concreto in ambito videoludico, potrebbe essere la creazione di una serie di nemici (Slime, Troll, Mage, Dragon) con comportamenti e attacchi diversi, tutti figli di un oggetto "Enemy" che ha delle funzioni e variabili base (Attack(), Move(), Destroy(), DropItem(), etc.).

Come possiamo notare, l'utilizzo di prototype accorcia notevolmente il lavoro, riducendo la mole di codice da scrivere. infatti possiamo sfruttare un oggetto generico per definire le variabili e funzioni in comune.

Ti consigliamo anche