I Sottomarini

Il sottomarino
Ecco il fantastico sottomarino. Mamma mia. Salvate quest'immagine in ./data chiamandola sottomarino.png.
Andiamo alla classe Sottomarino. Stavolta lo lascio come esercizio: ci servono due Image, una sottomarinoDx e una sottomarinoSx, esattamente come per la Nave.
Dobbiamo anche stravolgere del vecchio codice: la Box ora avrà dimensioni fisse, che saranno quelle dell'immagine del Sottomarino. Precedentemente era la classe StatoGioco a stabilire le dimensioni del Sottomarino. Adesso cambiamo le carte in tavola:
box = new Rectangle(0, 0, sottomarinoDx.getWidth(), sottomarinoDx.getHeight());
Di conseguenza, il metodo start sarà differente:
public void start(float x, float y, float speed) {
this.x = x;
this.y = y;
this.speed = speed;
this.box.setLocation(x, y);
active = true;
}
Anche qui mi chiedo a che cosa serva il duplicato delle coordinate x e y. Boh, magari più in là disaccoppiamo grafica e bounding box o roba simile, e allora verrebbero buone.
Dal momento che abbiamo modificato start, NetBeans diligentemente ci informerà di errori in StatoGioco. Andiamo lì e modifichiamo il metodo attivaSottomarino, levando dalle balle le variabili width ed height.
Le Bombe

Il sottomarino
Anche la Bomba ha il fiocchetto:) Solito discorso: salviamo l'immagine bomba.png in ./data.
Nella classe Bomba aggiungiamo un'Image:
private Image bomba;
Stavolta non ci serve la copia invertita, perché la Bomba ha una sola direzione di movimento. Nel costruttore usiamo queste due righe:
bomba = new Image("./data/bomba.png");
this.box = new Rectangle(x, y, bomba.getWidth(), bomba.getHeight());
Anche qui vale il discorso fatto precedentemente: Slick carica una sola versione dell'immagine bomba.png in memoria, quindi nessun problema anche se abbiamo 10 Bombe e 20 Sottomarini.
In render il codice sarà così:
if (active) {
bomba.draw(x, y);
}
Il fondo marino

Il fondo marino
Ho anche realizzato questo interessantissimo fondo marino. Salviamo l'immagine qui a sinistra in ./data/fondo marino.png.
Costruiamo una classe apposita per il Mare, perché magari poi ci aggiungiamo altre cose tipo i pesci o roba simile.
La classe la riporto qui intera, che tanto è piccola ed autoesplicativa:
public class Mare implements Entity {
private Image fondo;
public Mare() throws SlickException {
fondo = new Image("./data/fondo marino.png");
}
public void update(GameContainer container, StateBasedGame game, int delta) {
// Per ora non faccio nulla
}
public void render(GameContainer container, StateBasedGame game, Graphics g) {
fondo.draw(0, container.getHeight() - fondo.getHeight());
}
public Rectangle getBoundingBox() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
Il metodo getBoundingBox lancia un'eccezione, tanto non penso lo chiameremo mai. Tanto sapete come costruire una Box a partire dalle dimensioni di un'immagine.
Usare il Mare
In StatoGioco, aggiungeremo una variabile:
private Mare mare;
e lo costruiamo in enter. In realtà non è necessario, lo si può costruire anche nella init:
mare = new Mare();
Tanto per essere precisi, nella update aggiorniamo anche il Mare:
mare.update(container, game, delta);
Nella render, invece, vogliamo disegnare il Mare sotto a tutti gli altri. Quindi mettiamo la chiamata prima di tutte le altre:
mare.render(container, game, g);
Il colore del cielo
Come ultima cosa, andiamo in Applicazione e, nel metodo initStatesList aggiungiamo questa riga:
container.getGraphics().setBackground(new Color(154, 226, 255));
In questo modo tutto ad ogni giro, prima di disegnare qualsiasi altra cosa, Slick provvederà a cancellare lo schermo con l'azzurrino specificato dalla terna RGB che vedete qui sopra. Poi noi ci disegniamo sopra il Mare, e infine la Nave, i Sottomarini e le Bombe.
Nota
Mi sono accorto che, nella initStatesList, non c'è bisogno di chiamare la this.enterState(0), perché per qualche ragione si entra automaticamente nello stato StatoGioco quando viene aggiunto. Investigherò!