Home E-Books Effetti speciali e sviluppo giochi in Java slide show d'immagini

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 >>