Il JDK mette a disposizione molti strumenti per trattare con efficacia grafica e animazioni, tanto da consentirci di avere nel nostro browser degli effetti simili a quelli dei famosi "DEMO" scritti in C o Assembler. In questo articolo verrà presentata un applet che simula la neve che cade e che interagisce con quello che trova sul suo percorso.
Le classi utilizzate
In questo articolo esamineremo brevenente le classi MemoryImageSource e PixelGrabber e il loro utilizzo per costruire la nostra l'applet natalizia.*
Queste due classi fanno parte del package java.awt.image.\* e consentono qualsiasi elaborazione di un immagine (limitatamente alle prestazioni ), riferendoci ad essa attraverso un vettore di interi.
- Esaminiamo prima la MemoryImageSource che permette di creare un immagine a partire un vettore di interi opportunamente dimensionato, per esempio il seguente spezzone di codice alloca con questa tecnica un immagine 100x100:
........... int[] pixels; pixels = new int[100 * 100]; /* il primo e il secondo parametro sono la larghezza e l'altezza,il terzo è il vettore, il quarto l'offset e l'ultimo la larghezza dell'immagine */ MemoryImageSource imgsrc = new MemoryImageSource(100, 100, pixels, 0, 100); Image memimg = createImage(imgsrc); imgsrc.setAnimated(true); ...........
> Il metodo setAnimated (introdotto con il JDK 1.1) settato a true fa in modo che ogni volta che si richiama il metodo newPixels l'immagine a video venga aggiornata con le informazioni che si trovano nel vettore che contiene il colore di ogni pixel.
> Il codice che segue mostra come tracciare una linea obliqua dall'angolo superiore sinistro all'angolo inferiore destro di colore nero:
...... Color nero = new Color(0,0,0); for (int x=0;x<100;i++) pixels[x * 100 + x] = nero.getRGB(); /* newPixels( "area da aggiornare, in questo caso tutta l'immagine"); */ imgsrc.newPixels(0,0,100,100); .........
> NOTA: per individuare i pixel nell'array ho usato questa conversione:
> > Il pixel con coordinate X,Y si trova alla posizione > > > y \* Larghezza + x del vettore dove la variabile larghezza è la larghezza dell'immagine.
- Invece la PixelGrabber consente di copiare un oggetto Image in un buffer che per i nostri scopi può essere ancora una volta il solito array, per esempio:
Image img = getImage(getDocumentBase(),nome_immagine); pg = new PixelGrabber(img, 0, 0, LARGHEZZA, ALTEZZA, pixels, 0, LARGHEZZA);
Il frammento di codice sopra riportato trasforma l'immagine in una sequenza
di interi che vengono copiati nell'array "pixels" consentendo di
elaborare facilmente l'immagine agendo sul vettore in questione.
...LA TEMPESTA DI NEVE
Presa un pò di confidenza con queste due classi che il JDK ci mette a disposizione, è facile ideare un algoritmo che simuli la neve che cade; quella che segue è l'analisi per punti dell'algoritmo, per i dettagli implementativi rimando al codice sorgente completo snow.java.
- Prima di tutto le strutture dati fondamentali sono due array di interi:
x = new int[MAX_FIOCCHI]; y = new int[MAX_FIOCCHI];
che andranno a contenere le coordinate di ogni fiocco di neve;
Occorreranno anche altri due vettori che serviranno uno come maschera, e l'altro come buffer per la visualizzazione a video che dovranno essere opportunamente dimensionati per contenere l'immagine scelta.
pixels = new int[ALTEZZA * LARGHEZZA]; maschera = new int[ALTEZZA * LARGHEZZA];
Ora usando la classe MemoryImageSource come visto, creiamo una Image a partire dal vettore "pixels" e dopo aver caricato un immagine da usare come sfondo, utilizzando la classe PixelGrabber la riversiamo nel vettore "maschera" che ci servirà in seguito.
A questo punto inizializziamo le coordinate dei fiocchi di neve con dei valori random che per le x saranno compresi tra 1 e la larghezza dell'immagine utilizzata e per le y tra 1 e circa 1/5 dell'altezza.
Adesso ci servirà una funzione che ogni volta muova i fiocchi di neve ad ogni iterazione sapendo che se nel vettore "maschera" c'è il colore nero allora significa che non c'é nessun ostacolo e quindi il fiocco può proseguire per la sua strada, altrimnti se il colore è diverso dal nero vuol dire che c'è un ostacolo e quindi si dovrà deviare.
Schematicamente
per ogni fiocco di neve faccio i seguenti controlli:
Se
il pixel immediatamente sotto il fiocco è nero (
cioè "maschera[(y[i]+1) * LARGHEZZA + x[i]] == nero.getRGB()") allora
possiamo proseguire e incrementiamo la coordinata y del nostro fiocco di
neve;
Altrimenti
controllo con lo stesso metodo se i pixel immediatamente più in
basso a destra e a sinistra sono liberi e in caso affermativo rispettivamente
incremento o decremento la coordinata x di 1 e in etrambi i casi incremento
la y.
Se
neanche il punto (2) ha avuto successo allora il fiocco di neve è
arrivato in fondo e non si può muovere, quindi lo si memorizza
nella maschera (per tenerne conto alla prossima iterazione) e lo si rigenera
in modo casuale.
- Fatto questo non ci resta che inserire la funzione di movimento in un thread che la richiami ciclicamente e aggiorni ogni volta il video.
...e siamo pronti per dare il buon natale ai visitatori del nostro sito con questo nuovo effetto.
CONCLUSIONI
Questa applet non vuole essere niente di più che l'ennesimo esempio di come con un pò di fantasia e poche righe di java si può abbellire una pagina web (magari nel periodo natalizio) mentre l'articolo introduce le due classi MemoryImageSource e PixelGrabber messe a disposizione dal JDK per l'elaborazione delle immagini.
Ora non mi resta che augurare a tutti buon natale e felice 1998!
