cerca
Giochino del Sottomarino
modifica cronologia stampa login logout

Wiki

Tools

Categorie

Help

edit SideBar

Utenti.GiochinoSottomarino-Immagini History

Show minor edits - Show changes to output

Changed line 152 from:
%lframe width = 200px%Attach:sottomarino-fondomarino.png|'''Il fondo marino'''
to:
%lframe width=200px%Attach:sottomarino-fondomarino.png|'''Il fondo marino'''
Changed line 130 from:
%lframe%Attach:sottomarino-bomba.png|'''Il sottomarino'''
to:
%lframe%Attach:sottomarino-bomba.png|'''La bomba'''
Changed lines 104-105 from:
%lframe width = 200px%Attach:sottomarino-sottomarino.png|'''Il sottomarino'''
to:
%lframe%Attach:sottomarino-sottomarino.png|'''Il sottomarino'''
Changed line 130 from:
%lframe width = 200px%Attach:sottomarino-bomba.png|'''Il sottomarino'''
to:
%lframe%Attach:sottomarino-bomba.png|'''Il sottomarino'''
Changed line 27 from:
%lframe width = 200px%Attach:sottomarino-nave.png|'''La nave'''
to:
%lframe%Attach:sottomarino-nave.png|'''La nave'''
Added lines 24-25:
Per disegnare un'immagine usiamo il metodo '''draw'''. Ce ne sono varie versioni. Quella basica permette di specificare le coordinate '''x''' e '''y''' da cui far partire il disegno. Le ascisse vanno da sinistra a destra, mentre le ordinate dall'alto in basso. Quindi, '''y = 0''' corrisponde alla cima dello schermo.
Changed lines 103-106 from:

to:
!!I Sottomarini
%lframe width = 200px%Attach:sottomarino-sottomarino.png|'''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 -> GiochinoSottomarino-SottomariniBombe]] 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
%lframe width = 200px%Attach:sottomarino-bomba.png|'''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
%lframe width = 200px%Attach:sottomarino-fondomarino.png|'''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ò!
Added lines 1-109:
(:title Giochino del Sottomarino:)

<<|[[Giochino Sottomarino]]|>>

%titolo%''':: Giochino del Sottomarino - Immagini ::'''

!!Un po' di grafica
Attenzione: ho realizzato alcune immagini, ma non sono esattamente ''belle''. Spero servano a rendere l'idea. Se poi qualcuno di più dotato decide di collaborare, ne sarei ben felice:)

!!!Dove mettere le immagini
Nella cartella del nostro progetto creiamo una nuova cartella, chiamandola ''data''. Ad esempio, se il nostro progetto si trovava in

/home/dario/NetBeansProject/Sottomarino

la cartella sarà

/home/dario/NetBeansProject/Sottomarino/data

!!Image
La classe '''Image''' fornita da Slick è il sistema attraverso cui passa il caricamento di immagini da files, il loro trasferimento in memoria video e il loro successivo rendering.

La costruzione di un''''Image''' può causare una '''SlickException'''. NetBeans avviserà, e l'opzione che scelgo è di solito quella di far aggiungere a NetBeans la clausola relativa all'eccezione. In questo modo se qualcosa va storto il programma si pianta. Non è il massimo della vita, in realtà, però soprattutto in questa fase è bello sapere che le cose non stanno funzionando, così le sistemiamo:)

!!La Nave
%lframe width = 200px%Attach:sottomarino-nave.png|'''La nave'''

La '''Nave''' che ho realizzato ha un bel fiocchetto in stile Hello Denis. Salvate l'immagine qui a sinistra in '''/data''' e chiamatela '''nave.png'''.

Andiamo nella classe '''Nave'''. Aggiungiamo due variabili, una per la '''Nave''' in direzione "normale", cioè rivolta a destra, e una per la '''Nave''' rivolta a sinistra.

private Image naveDx;
private Image naveSx;

Nel costruttore di '''Nave''' mettiamo

naveDx = new Image("./data/nave.png");
naveSx = naveDx.getFlippedCopy(true, false);

Con la prima riga diciamo a '''Slick''' di caricare l'immagine '''nave.png''' dalla cartella '''/data''' a partire dalla cartella base del progetto. La '''naveSx''' è una copia invertita di '''naveDx'''. I due parametri sono due booleani che dicono se è invertita sull'asse delle X, e se invertita sull'asse delle Y. Provate per vedere quello che esce.

Quello che internamente '''Slick''' fa è di tenere via in memoria video ''una sola copia'' dell'immagine caricata. Le '''Image''' create a partire da questa possono essere viste come delle modalità di accesso a questa texture. Quindi non c'è nessun problema a caricare più copie della stessa immagine, cosa che accadrà con le bombe.

!!!Dimensioni della nave
Ovviamente le dimensioni della '''Nave''' ora dovranno essere quelle dell'immagine caricata. Di conseguenza, anche la '''Box''' dovrà avere dimensioni diverse.

box = new Rectangle(x, y, naveDx.getWidth(), naveDx.getHeight());

!!!Direzione della Nave
Per sapere quale nave disegnare, introduciamo un nuovo booleano in '''Nave''':

private boolean direction;

e stabiliamo che se andiamo a destra lo mettiamo a '''true''', se andiamo a sinistra lo mettiamo a '''false'''.

public void goLeft() {
direction = false;
this.speed = maxSpeed;
}

public void goRight() {
direction = true;
this.speed = maxSpeed;
}

Non ricordo se avevo già introdotto la variabile '''maxSpeed''', ma comunque è un '''float''' e nel costruttore lo mettiamo così:

maxSpeed = 50.0f / 1000.0f;

che vuol dire che la nostra nave farà 50 pixel al secondo. Wow!

Andiamo al metodo '''update'''. Per sapere in che direzione sta andando la '''Nave''', usiamo la variabile '''direction''':

int dirMult = (direction ? 1 : -1);

x += speed * delta * dirMult;

if ((x + box.getWidth()) > container.getWidth()) {
x = container.getWidth() - box.getWidth();
}

if (x < 0) {
x = 0;
}

Questo codice controlla anche che la '''Nave''' non esca dallo schermo. Lasciamo com'era la riga che aggiornava la posizione della '''Box'''.

Ma a che serve '''dirMult'''? In effetti, per ora a niente. Maggiori info nelle prossime puntate:)

Passiamo al metodo '''render''':

if (direction) {
naveDx.draw(box.getX(), box.getY());
} else {
naveSx.draw(box.getX(), box.getY());
}

Domanda: se uso la '''Box''' per avere le coordinate, a che mi servono le variabili '''x''' e '''y'''? Boh, per ora mi pare che non servano, penso si possano togliere:)

Ad ogni modo, così facendo la '''Nave''' viene disegnata nell'ultima direzione che aveva prima di fermarsi. Questo perché quando la fermiamo mediante '''stop''' la '''direction''' non viene modificata.






<<|[[Giochino Sottomarino]]|>>

----
[[!Guide]]