
Vi ricordate la nostra ultima lezione con libgdx? Eravamo rimasti alla creazione del nostro mondo e del personaggio principale del gioco che andremo a sviluppare. Sostanzialmente creeremo tre classi: la prima è Bob.java, mentre le restanti saranno World.java e Block.java, le quali ci serviranno per costruire il “palcoscenico” dell’opera che creeremo. Naturalmente, procederemo per passi nell’implementazione delle varie componenti del videogame, dandovi i concetti basilari dello sviluppo con libgdx, in modo tale da consentirvi di approfondire facilmente il vostro eventuale studio futuro. Se siete pronti, possiamo iniziare.
Iniziamo, dunque, con il personaggio principale che già abbiamo menzionato: Bob. Di seguito il codice della classe che utilizzeremo per esso:
package it.androidblog.starassault; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; public class Bob { public enum State { IDLE, WALKING, JUMPING, DYING } static final float SPEED = 2f; // unit per second static final float JUMP_VELOCITY = 1f; static final float SIZE = 0.5f; // half a unit Vector2 position = new Vector2(); Vector2 acceleration = new Vector2(); Vector2 velocity = new Vector2(); Rectangle bounds = new Rectangle(); State state = State.IDLE; boolean facingLeft = true; public Bob(Vector2 position) { this.position = position; this.bounds.height = SIZE; this.bounds.width = SIZE; } }
Dalla linea 16 alla linea 21 abbiamo definito gli attributi di Bob. Essi definiranno a loro volta lo stato di Bob in ogni istante di gioco. Vediamo, insieme, quali sono:
- position: definisce la posizione di Bob nel mondo che costruiremo, esso viene espresso in coordinate;
- acceleration: riguarda l’accelerazione di Bob quando salta;
- velocity: determina la velocità di Bob durante i movimenti;
- bounds: come facciamo a sapere quando Bob si imbatte in un muro o viene colpito da un proiettile? Ogni elemento di gioco sarà contenuto in un rettangolo che potrà essere utilizzato per rilevare le collisioni;
- state: lo stato corrente di Bob;
- facingLeft: poiché abbiamo a che fare con un gioco 2D, avremo bisogno solamente di due facce, destra e sinistra.
Dalla linea 12 alla 14, invece, definiamo delle costanti che ci serviranno per calcolare velocità e posizione del personaggio. A questo punto, se non avete dubbi su tutto ciò che avete visto finora, possiamo procedere con la creazione di Block.java:
package it.androidblog.starassault; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; public class Block { static final float SIZE = 1f; Vector2 position = new Vector2(); Rectangle bounds = new Rectangle(); public Block(Vector2 pos) { this.position = pos; this.bounds.width = SIZE; this.bounds.height = SIZE; } }
Come potete constatare voi stessi, si tratta di una classe molto semplice che rispecchia il suo nome. Essa costituisce un semplice “blocco” nel vero senso della parola (proprio come abbiamo visto nel mock-up della lezione precedente). Il suo utilizzo è facilmente intuibile, ma lo capirete ancora meglio tra poco quando creeremo World.java.
Avrete notato di certo l’utilizzo del tipo Vector2 di libgdx. Esso è molto utile e comodo poiché ci fornisce tutto l’occorrente per lavorare con vettori euclidei. Lo utilizzeremo per entità di posizione, per calcolare velocità e molto altro ancora.
Prima di creare World.java, tuttavia, apriremo una piccola parentesi sul sistema di coordinate e sulle unità. Come nel mondo reale abbiamo delle dimensioni e un’unità di misura, lo stesso avremo con libgdx. Sbarazzandoci della terza dimensione, la gestione del nostro mondo sarà molto semplice, i blocchi costituiranno il terreno e gli ostacoli, ma naturalmente abbiamo bisogno di un’unità di misura. L’immagine qui di seguito vi chiarirà le idee.
I quadrati rossi sono i blocchi, il sistema di riferimento ha origine in basso a sinistra. Se, ad esempio, Bob dovesse camminare ad una velocità di 10.000 unità all’ora, significa che la sua posizione (la coordinata X per la precisione) varierà di 2.7 unità al secondo.
Una volta compresi questi meccanismi basilari possiamo iniziare la creazione del nostro mondo. Esso sarà composto da dieci unità in larghezza e sette in lunghezza, ma onde evitare incomprensioni, seguiremo l’immagine di seguito per svilupparlo.
Passiamo, ora, alla creazione di World.java:
package it.androidblog.starassault; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; public class World { /** The blocks making up the world **/ Array<Block> blocks = new Array<Block>(); /** Our player controlled hero **/ Bob bob; // Getters ----------- public Array<Block> getBlocks() { return blocks; } public Bob getBob() { return bob; } // -------------------- public World() { createDemoWorld(); } private void createDemoWorld() { bob = new Bob(new Vector2(7, 2)); for (int i = 0; i < 10; i++) { blocks.add(new Block(new Vector2(i, 0))); blocks.add(new Block(new Vector2(i, 7))); if (i > 2) blocks.add(new Block(new Vector2(i, 1))); } blocks.add(new Block(new Vector2(9, 2))); blocks.add(new Block(new Vector2(9, 3))); blocks.add(new Block(new Vector2(9, 4))); blocks.add(new Block(new Vector2(9, 5))); blocks.add(new Block(new Vector2(6, 3))); blocks.add(new Block(new Vector2(6, 4))); blocks.add(new Block(new Vector2(6, 5))); } }
Come potete vedere, al momento abbiamo un semplice contenitore. Le entità all’interno sono Bob e i blocchi. Inseriremo le classi nella sotto-cartella model, ma vedremo tutto questo e maggiori dettagli sullo sviluppo libgdx (in modo da vedere anche i primi risultati con i nostri occhi) nelle prossime lezioni.