Effetti speciali e sviluppo giochi in Java(TM) -Uno slide show di immagini (SlideShow) configurabile e pieno d'effetti
di Anibal Wainstein (traduzione di Hanami Solutions)
4.1.4 Uno slide show di immagini (SlideShow) configurabile e pieno d'effetti
Anche se AppletAnimator II si può usare per
mostrare immagini, non è ancora molto impressionante.
Svilupperemo ora uno slide show animato che lentamente effettui
la traslazione dell'immagine da un punto a caso finché
non copra la vecchia immagine completamente.
Stiamo finalmente per usare i numeri casuali. Esiste una classe
in Java davvero utile chiamata Math. Questa classe contiene
per lo più metodi statici, quindi non avete bisogno di
creare un oggetto Math per usarle, potete invocarle direttamente.
Un metodo importante è il metodo random(). Restituisce un
numero casuale in virgola mobile a doppia precisione compreso tra
0 e 0.9999999... Moltiplicandolo per 10, ottenete numeri casuali
tra 0 e 9. Vi prego di notare che quando effettuate un type cast da
double a intero, il numero viene arrotondato al valore dell'intero più basso.
Osservate la seguente riga:
int randomnumber = (int)(Math.random()*2.0);
La variabile "randomnumber" verrà
impostata a 0 o 1. Nello slide show useremo numeri casuali
per indicare da quale angolo un'immagine verrà traslata.
Per fare in pratica questa applet, ci limitiamo a prendere tutte
le variabili e i metodi della applet AppletAnimatorII e li usiamo
con un solo cambiamento nei metodi run() e paint().
Dobbiamo anche aggiungere le seguenti variabili globali sotto la
dichiarazione della variabile "currentimage":
int nextimage = 0; int nextimagexposition = 0; int nextimageyposition = 0;
Queste variabili indicano quale immagine sarà animata nello
schermo della applet e quale sia la sua posizione attuale. Il
metodo paint() apparirà quindi come segue:
public synchronized void paint(Graphics g)
{ g.drawImage(images[currentimage],0,0,this);
//L'immagine seguente viene tracciata sopra la
//precedente.
g.drawImage(images[nextimage]
,nextimagexposition,nextimageyposition,this);
}
Il metodo run() sarà un pò più complicato.
Dobbiamo trovare quali siano le dimensioni della applet perché
chi userà l'applet probabilmente ne cambierà le
dimensioni. Ci riuscirete col metodo size(), che restituisce
un oggetto Dimension. Con questo oggetto, possiamo trovare le
dimensioni della applet tramite le sue variabili interne,
"width" e "height".
public void run()
{ //Dobbiamo trovare la dimensione della applet e salvarla
//nella variabile "d". Possiamo ottenere ora larghezza e altezza
//della applet scrivendo d.width e d.height.
Dimension d=size();
//Le variabili "displacement" specificano le
//coordinate iniziali della immagine. int displacementx=0; int displacementy=0;
//"pathsize" la userete per conoscere a quale distanza
//verrà spostata la nuova immagine. int pathsize=0;
//"currentimage" viene inizializzata alla prima immagine,
//seguita dall'immagine seguente, che diventa l'immagine
//numero 2, e così via. currentimage=0;
nextimage=1; while (true)
{ //Calcoliamo da quale direzione
//debba arrivare la nuova immagine. int directionx=(int) (Math.random()*3.0)-1; int directiony=(int) (Math.random()*3.0)-1; //"directionx" e "directiony" possono avere
//tre valori: -1, 0 e 1. Non vogliamo che
//entrambe le variabili abbiano valore 0
//contemporaneamente quindi cambiamo
//"directiony" per rendere l'effetto
//più interessante. if (directionx==0 && directiony==0) directiony=1;
//La variabile "pathsize" contiene larghezza o altezza
//della applet a seconda di quale lato sia il più
//corto. if (d.width<d.height) pathsize=d.width; else pathsize=d.height;
//La riga seguente ci protegge dal problema
//che sorgerebbe se l'utente dovesse specificare una sola
//immagine. if (nextimage>maxitems-1) nextimage=0;
//Il seguente ciclo gestisce l'aggiornamento dello schermo
//durante l'animazione. Sposterà l'immagine
//il numero di volte specificato da "pathsize",
//che è il lato più corto dello schermo dell'applet. for (int i=0; i<=pathsize; i++)
{ //Le posizioni dell'immagine si spostano
//della frazione (i/pathsize).
nextimagexposition=displacementx
-directionx*(i*d.width)/pathsize;
nextimageyposition=displacementy
-directiony*(i*d.height)/pathsize;
update(getGraphics()); try {Thread.sleep(sleeptime);} catch(InterruptedException e) {}
} //Quando la traslazione è finita,
//"currentimage" viene impostato alla nuova
//immagine.
currentimage=nextimage;
//Incrementiamo "nextimage" di modo che punti alla
//immagine successiva. Allo stesso tempo ci assicuriamo che
//"nextimage" si estenda oltre l'indice dell'array ma
//che sia costretto a ricominciare da 0 se lo fa.
nextimage++;
if (nextimage>maxitems-1) nextimage=0;
}
L'applet parte col piazzare un'immagine fuori dal campo visivo
dello spettatore, ovvero fuori dallo schermo della applet. Lentamente
l'immagine viene traslata al centro, un pixel per volta.
Un problema che si può presentare in questa situazione, è
l'eventualità che l'applet sia un rettangolo e non un quadrato.
Perché in quel caso l'applet dovrebbe muovere l'immagine
con incrementi differenti tra lo spostamento orizzontale e quello
verticale. Per questa ragione useremo il lato corto dello schermo della
applet e l'useremo nel ciclo for per contare il numero
di pixels (la variabile "pathsize"). Calcoliamo
una percentuale di quanto si debba muovere l'immagine (i/pathsize)
e moltiplichiamola per d.width o d.height per ottenere
la distanza orizzontale e verticale totale di quanto sia stata traslata
e le nuove posizioni x e y dell'immagine.
Il problema qua è che, dato che stiamo lavorando con gli interi,
dobbiamo far continuare le divisioni. Quindi scriviamo piuttosto ((i*d.width)/pathsize).
Altrimenti (i/pathsize) darebbe sempre come risultato
zero perché il valore di "pathsize" è più grande di
"i". Questo concetto è importante, se dividete
un intero più piccolo per uno più grande, il risultato
è sempre zero.
In ultimo dobbiamo anche moltiplicare questa espressione per "directionx"
o "directiony", di modo che l'immagine si sposti nella
direzione giusta e sottrarre questa espressione da "displacementx"
e "displacementy" rispettivamente, queste due sono le
coordinate di partenza delle immagini.

L'immagine mostra come lo slide show
funziona. La nuova immagine "nextimage" viene traslata
sulla vecchia "currentimage".
Dopo il ciclo for, impostiamo "currentimage"
perché indichi la nuova immagine e incrementiamo "nextimage"
perché punti all'immagine successiva nello slide show. Se
"nextimage" punta all'ultima immagine, allora l'impostiamo
a zero, di modo che punti invece alla prima immagine
(indice zero). The risultato è che le immagini si avvicendano
nello slide show in maniera ciclica, così che l'effetto non finisca
mai. Questa riga deve essere usata anche prima del ciclo for, nel caso che
l'utente per assurdo voglia specificare come parametro dell'applet una sola immagine.
Questo deve essere fatto per evitare che l'applet si inchiodi.
Potete ora visionarne il risultato clickando
qui.
Siete delusi, vero? Tutta questa fatica
per una applet che sfarfalla! Il problema con l'applet
è che quando la prima immagine è stata tracciata
nel metodo paint() con drawImage(), allora lo schermo dell' applet
viene aggiornato immediatamente. Mostrerà quindi per intero la vecchia
immagine prima che ci sia tempo di coprirla con l'immagine successiva.
Dobbiamo quindi trovare un modo di impedire allo schermo della applet di
essere aggiornato tra le due invocazioni di drawImage(). Qui abbiamo
occasione di usare la tecnica double buffering che discuteremo
nella prossima sezione di questo capitolo.
Pagina seguente >>
|