Effetti speciali e sviluppo giochi in Java(TM) -Double buffering
di Anibal Wainstein (traduzione di Hanami Solutions)
4.2 Double
buffering
Il double buffering è una tecnica usata in quasi
ogni linguaggio di programmazione da chi sviluppa giochi ed effetti speciali.
Quando tracciate linee, rettangolo, testo e immagini direttamente
su schermo, potete in via di principio vedere quando ognuno di questi oggetti
viene disegnato. Questo non va bene se volete che lo spettatore
veda solo il risultato finale e nient'altro. Come abbiamo visto con gli
esempi textscroller
e slideshow, questo può
causare sfarfallii. Per evitarli, dovete disegnare prima in un buffer
(ecco perché si chiama "double buffering"). Il
buffer è una immagine che tracciate "di nascosto"
e non mostrate allo spettatore finché non è finita.
In Java l'ottenete creando una immagine larga quanto l'applet,
e collegate a questa immagine un oggetto Graphics.
Quando avete finito di tracciarla invocate il metodo paint()
che mostra l'immagine contenuta nel buffer su schermo.
4.2.1 SlideShow
II, ora senza sfarfallii
Per aggiungere il double buffering alla applet slideshow
della scorsa sezione, dobbiamo prima dichiarare una variabile globale Image
e una variabile Graphics che inizializziamo col metodo init().
Aggiungete le seguenti variabili alle variabili globali della applet
(aggiungetele sotto la dichiarazione della variabile "nextimagepositiony"):
//"bufferimage" vien usato come buffer e
//"bufferg" viene usato per tracciare in questo buffer.
Image bufferimage;
Graphics bufferg;
//"delay" verrà usato al posto di "sleeptime" per
//il ritardo di ogni animazione. "sleeptime" verrà piuttosto usato per
//aggiungere un ritardo configurabile tra ogni immagine.
int delay=0;
Ormai che abbiamo cominciato a cambiare la
applet, cogliamo l'occasione per aggiungere un nuovo parametro,
"delay". Questa variabile verrà usata al posto di "sleeptime"
come ritardo nell' animazione. La variabile "sleeptime"
verrà invece usata come pausa tra ogni immagine che si avvicendi.
Ora l'utente di questa applet potrà specificare un ritardo
prima che venga animata l'immagine successiva. Per creare il
buffer grafico digitiamo le seguenti righe e le aggiungiamo in fondo al
metodo init():
//Restituisce le dimensioni della applet.
Dimension d=size();
//createImage() crea un'immagine vuota
//con le stesse dimensioni dello schermo
//della applet.
bufferimage=createImage(d.width,d.height);
//"bufferg" è ora associato al
//buffer dell'immagine.
bufferg=bufferimage.getGraphics();
delay=getIntegerParameter("delay",10);
La sola cosa che dobbiamo fare ora è di fare in modo che
le due immagini siano tracciate prima nel buffer e non
direttamente su schermo. Questo l'otteniamo col metodo paint():
public synchronized void paint(Graphics g)
{
//Controlliamo per prima cosa che "bufferg"
//sia inizializzato, non è sempre detto che
//lo sia.
if (bufferg!=null)
{
//Tracciamo prima le due immagini nel buffer.
bufferg.drawImage(images[currentimage],0,0,this);
bufferg.drawImage(images[nextimage]
,nextimagexposition,nextimageyposition,this);
//Ora tracciamo l'immagine presente nel buffer sullo schermo
// della applet.
g.drawImage(bufferimage,0,0,this);
}
}
Servono alcune modifiche anche nel metodo
run(), ora che abbiamo cambiato i parametri:
public void run()
{
Dimension d=size();
int displacementx=0;
int displacementy=0;
int pathsize=0;
currentimage=0;
nextimage=1;
while (true)
{
int directionx=(int) (Math.random()*3.0)-1;
int directiony=(int) (Math.random()*3.0)-1;
if (directionx==0 && directiony==0) directiony=1;
if (d.width<d.height) pathsize=d.width;
else pathsize=d.height;
displacementx=directionx*d.width;
displacementy=directiony*d.height;
if (nextimage>maxitems-1) nextimage=0;
for (int i=0; i<=pathsize; i++)
{
nextimagexposition=displacementx
-directionx*(i*d.width)/pathsize;
nextimageyposition=displacementy
-directiony*(i*d.height)/pathsize;
update(getGraphics());
//Ora "delay" è il distacco temporale nel ciclo.
try {Thread.sleep(delay);}
catch(InterruptedException e) {}
}
//"sleeptime" viene usato fuori dal ciclo.
try {Thread.sleep(sleeptime);}
catch(InterruptedException e) {}
currentimage=nextimage;
nextimage++;
if (nextimage>maxitems-1) nextimage=0;
}
}
Aggiungiamo un nuovo ritardo fuori dal ciclo for e
usiamo qui la variabile "sleeptime". Ora l'utente della
applet può specificare un ritardo prima che l'immagine successiva
inizi a fare il suo ingresso. Ora l'applet dovrebbe essere finita del tutto.
Non dimenticate di aggiungere il parametro HTML "delay"
e impostarlo a 20 prima di provare l'applet. Impostate il parametro
"sleeptime" a 1000 millisecondi o un valore superiore.
Clickate qua per ammirare l'applet. Non è bellissima?
Pagina seguente >>
|