(:title Giochino del Sottomarino:)
<< Classi principali: Entity e Nave | Giochino Sottomarino | Collisioni >>
:: Giochino del Sottomarino - Sottomarini e bombe ::
Il Sottomarino
Il Sottomarino è il nostro nemico. Per ora niente immagini, però possiamo comunque inventarci una classe ed infilarla nel gioco.
Così come la nave, il Sottomarino avrà una posizione, delle dimensioni ed una velocità:
private float x;
private float y;
private float speed;
private boolean active;
private Rectangle box;
active ci dice se il sottomarino è attivo o meno. A che cosa serve? Ora lo spiego.
La meccanica di gioco prevede che ogni tot secondi un sottomarino parta da un lato dello schermo ad una profondità variabile e con una velocità variabile. Potremmo quindi, ogni tot secondi, istanziare un nuovo sottomarino e farlo partire nel gioco. Non è una cosa sbagliata, non stiamo istanziando l'universo mondo e quindi non si tratterebbe di nulla di pesante. Però vogliamo usare un altro sistema, un po' differente, che ci permette di limitare anche il numero massimo di sottomarini che stanno contemporaneamente sullo schermo. Dei mille modi per ottenere ciò, qui ne presenterò uno.
Nel costruttore del sottomarino mettiamo dei valori di inizializzazione:
public Sottomarino() {
x = 0f;
y = 0f;
speed = 0f;
box = new Rectangle(0, 0, 100, 100);
active = false;
}
e ci premuriamo di lasciare il sottomarino inattivo. Per farlo partire ci serviamo di un altro metodo, start, in cui gli passeremo posizione, dimensione e velocità.
public void start(float x, float y, float width, float height, float speed) {
this.x = x;
this.y = y;
this.speed = speed;
this.box.setBounds(x, y, width, height);
this.active = true;
}
Questo vuol dire che lo StatoGioco, quando ci ha voglia, si inventerà delle dimensioni e una posizione e dirà ad un Sottomarino di assumere quella forma e di partire alla ventura.
Il metodo render è il solito, visto che per ora non ci sono immagini:
public void render(GameContainer container, StateBasedGame game, Graphics g) {
if (active) {
g.draw(box);
}
}
Nel metodo update invece dobbiamo tenere conto della speed per avere un controllo in più: se il sottomarino esce dallo schermo, deve essere disattivato.
public void update(GameContainer container, StateBasedGame game, int delta) {
if (active) {
x += speed * delta;
if ((speed > 0 && x + box.getWidth() > container.getWidth())
|| (speed < 0 && x < 0))
{
active = false;
Log.info("Sottomarino fuori schermo");
}
box.setLocation(x, y);
}
}
A seconda della speed la condizione per sapere se il Sottomarino è uscito dallo schermo è differente. La chiamata Log.info viene completata automaticamente con CTRL-SHIFT-I, e si tratta di una utility interna a Slick.
I Sottomarini nello StatoGioco
Nello StatoGioco voglio avere una lista di Sottomarini, e la dichiaro così:
private ArrayList<Sottomarino> nemici;
Nel metodo enter popolerò questa lista:
nemici = new ArrayList<Sottomarino>();
for (int i = 0; i < 20; i++) {
nemici.add(new Sottomarino());
}
In update mi preoccupo di aggiornare tutti i sottomarini:
for (Sottomarino s : nemici) {
s.update(container, game, delta);
}
e in render li disegnerò tutti:
for (Sottomarino s : nemici) {
s.render(container, game, g);
}
Quando li faccio partire? Il Timer
Ma quando li faccio partire? Ogni tot tempo, si era detto. La cosa più semplice è la seguente: tenere via una variabile ed incrementarla con il valore di delta ad ogni giro. Se supera un certo valore, allora scateno un evento.
Questa è una cosa piuttosto comune e di facile implementazione. Ma voglio sfruttarla per introdurre una cosuccia che magari non tutti conoscono, e cioè la classe anonima.
Innanzitutto, decido di creare una nuova classe e di chiamarla Timer. Questa nuova classe contiene un valore di tempo da raggiungere ed il tempo trascorso finora, e viene aggiornata con il classico update. Per renderla un filo più completa deve anche essere possibile farla partire, fermarla, metterla in pausa. Quando il tempo è trascorso, il Timer deve automaticamente scatenare un certo evento.
Come faccio a fargli memorizzare un evento? Siccome siamo in Java, si tratterà di un oggetto. Decido che l'evento sia un'istanza dell'interfaccia Runnable. Viene usata di solito per i thread, e quindi è già esistente, è semplice e fa per noi. L'unico metodo che ha è run. Quello che succederà sarà quindi questo:
- creo un'istanza di Runnable
- nel metodo run ci metto il codice del mio evento
- passo il tutto al Timer e lo faccio partire
- aggiorno il timer nella update dello StatoGioco
- quando l'evento viene scatenato, faccio ripartire il Timer
Siccome la classe Timer è lunghetta, non la posto tutta, ma la allego.
<< Classi principali: Entity e Nave | Giochino Sottomarino | Collisioni >>
Guide