Negli articoli precedenti abbiamo esplorato le capacità di
interattività del Java costruendo delle interfacce, che possono risultare
molto utili. Una pagina web, comunque, oltre ad essere utile deve essere
attraente e gradevole: questo risultato si ottiene molto più agevolmente
se ci sono animazioni e suono, e il Java anche in questo campo può
rendersi molto utile.
Normalmente le icone animate vengono ottenute tramite
il GIF89, ossia una estensione del comune formato GIF che contiene più di
una immagine, in grado di visualizzarle in sequenza.
Questo sistema è
perfetto per alcune cose, ma molto limitato. Si pensi soltanto al fatto che non
si possono associare effetti sonori sincronizzati nei punti giusti della piccola
animazione, e soprattutto che non è possibile alcun cambiamento a seguito
di interazione con l'utente.
Supponiamo ad esempio di voler visualizzare una
simpatica animazione che rappresenti un operaio che piccona, a simboleggiare i
lavori in corso sulla nostra pagina, dove si senta anche il colpo della
picconata nel momento giusto.
L'unica soluzione multipiattaforma per questo
problema è il Java, specialmente se si volesse aggiungere qualche tocco
di interattività, ad esempio l'operaio che si gira verso l'osservatore
quando è clickato col mouse.
Lasciando al lettore il compito di
aggiungere interattività o altri upgrade, voglio proporre la prima
applet, che programmai nel Dicembre 1995, al tempo in cui il Java era sempre
alla Alpha version. Si tratta, infatti, di una semplicissima applet che carica
una serie di immagini .gif e un campione audio, e visualizza il tutto secondo le
nostre preferenze.
Il multithreading.
Il Java supporta il multithreading, ossia la capacità di eseguire
contemporaneamente più "flussi di esecuzione". Per esempio
possiamo far "partire" un thread che disegna dei quadrati e subito
dopo un'altro che disegna dei cerchi, e vedremmo disegnare contemporaneamente
cerchi e quadrati. Se cambiamo la priorità tra i thread, potremo veder
disegnare più "spesso" una figura rispetto ad un'altra.
Questa
caratteristica è molto potente, se ben usata, ma porta anche a molti
problemi e difficoltà, legati ai metodi synchronized e ai casi di
deadlock (blocco morto).
Per la nostra semplice animazione basterà un
singolo thread (monothreading), e in particolare il metodo sleep() che ci
permetterà di sospendere e riprendere l'esecuzione del thread, secondo le
nostre esigenze di sincronizzazione e velocità di replay.
Per dotare
la nostra applet di un thread dobbiamo aggiungere "implements runnable"
alla sua definizione, in modo che l'interfaccia runnable venga implementata, col
relativo metodo run(). Abbiamo visto che appena l'applet è caricata,
viene eseguito il metodo init().
A questo punto il controllo passa al metodo
start(), eseguito all'avvio e ad ogni eventuale riavvio, se si torna alla pagina
contenente l'applet. Infatti, cambiando pagina l'applet diviene invisibile, ma
rimane in funzione, rallentando silenziosamente le operazioni: è per
questo che è eseguito il suo metodo stop(), nel quale si fermano le
eventuali azioni continue.
Se si torna alla pagina dell'applet col pulsante "back"
del browser o da un link, il metodo start() sarà rieseguito, in modo che
sia possibile riattivare ciò che si era disattivato con stop().
Sulla
rete a volte si trovano applet di animazione programmate in modo approssivativo,
non avendo un appropriato start() e stop() per bloccare e riavviare le onerose
operazioni di ridisegno continuo: dopo averle caricate, l'unico modo per
liberarsi dal rallentamento generale nella navigazione è chiudere e
ricaricare il browser. ricapitolando:
public void init() { ... } // operazioni da
eseguire
// subito dopo il caricamento.
public void start() { ...
} // Avvio (o riavvio) dell'applet
public void stop() { ... } //
Arresto dell'applet
E' a questo punto che fa la sua comparsa il thread: nel metodo start() lo
istanzieremo e lo faremo partire, mentre nel metodo stop() lo bloccheremo. Il
codice del thread si deve trovare nel metodo run(), che viene eseguito una sola
volta, quindi metteremo un while() sempre vero in modo da creare un ciclo
infinito all'interno del quale inserire il codice per cambire fotogramma
adeguatamente. L'unico modo per interrompere l'animazione sara' quello di
cambiare pagina.
Per evitare che i fotogrammi siano scambiati troppo
velocemente, è indispensabile far "addormentare" il thread col
metodo sleep(numero microsecondi da attendere), che è posto
strategicamente tra uno scambio e l'altro.
Il caricamento delle immagini.
Caricare grafica dalla rete è molto semplice, basta usare il metodo
getImage(), e controllare lo stato del caricamento con il mediatracker. In
pratica, basta dichiarare un array di immagini grande abbastanza da contenere
tutti i fotogrammi, che nel nostro caso sono .gif, ma potrebbero anche essere
.jpg.
A questo punto con getImage(URL immagine da caricare) si fa iniziare
il caricamento. Attenzione al fatto che il programma continua l'esecuzione dopo
il getImage() anche se il caricamento non è terminato, e ci si può
trovare a visualizzare l'animazione con i fotogrammi caricati solo in parte. Per
attendere il termine del caricamento è sufficiente "puntare" un
mediatracker sull'immagine in caricamento e attendere il completamento tramite
il metodo waitForID(numero ID selezionato precedentemente con addImage):
mTracker.addImage(imgs[i], i);
try {
mTracker.waitForID(i);
}
catch(Exception e) {}
In
questo modo continuiamo l'esecuzione solo ad immagini completamente caricate.
Il caricamento dei suoni.
La gestione dell'audio in Java non è molto elaborata, almeno nella
versione attuale, dato che sono supportate riproduzioni soltanto di suoni mono a
8000 Hz in formato .AU, un formato proprietario della Sun. E' possibile suonare
più campioni contemporaneamente, ma la sincronizzazione non è
eccelsa.
Comunque, anche se per una gestione audio di qualità MIDI
probabilmente dovremo aspettare Java 2.0, per suonare un colpo di piccone al
momento giusto è più che sufficiente.
Ecco come si dichiara,
carica e suona un campione audio (detto AudioClip):
AudioClip suono = null;
suono = getAudioClip(base, "audio/piccon.au");
suono.play();
Probabilmente
è più complesso ottenere l'AudioClip in formato .AU: avrete
sicuramente presenti i più comuni formati .waw, .voc e .iff usati per i
campioni audio, ma i programmi di campionamento quasi mai salvano direttamente
in .au.
Nessun problema, basta munirsi di un programma in grado di
convertire i .waw in .au, ad esempio il GoldWave:
Goldwave page
Ricordatevi di
scalare il campione a 8000 Hz mono prima di salvare.
Istruzioni d'uso dell'applet.
Alcuni parametri sono modificabili da HTML (listato 2), mentre altri, come
il colore di sfondo, solo da sorgente .java (listato 1).
Ricordatevi che i
tag WIDTH e HEIGHT dell'applet devono indicare la grandezza esatta dei
fotogrammi.
Col paramentro "img" si indica il nome
dell'animazione, e l'eventuale subdirectory dove si trova. Nel nostro esempio i
fotogrammi si trovano nella subdirectory /anim e i fotogrammi si chiamano
ani0.gif, ani1.gif eccetera, quindi il parametro da inserire è "anim/ani".
Da notare che si usa / e non \, secondo lo standard unix. I parametro "quantifr"
indica il numero di fotogrammi, il parametro "veloc" indica i
millisecondi da attendere tra un fotogramma e l'altro, mentre il parametro "pausa"
indica la pausa in millisecondi che si deve attendere alla fine dell'animazione
prima di ricominciare.
Il movimento di un operaio che piccona è del
tipo detto "ping-pong", quindi è implementato questo tipo di
animazione.
Le animazioni possono essere cicliche (ossia si parte dal primo
fotogramma e si visualizzano in sequenza tutti gli altri, fino all'ultimo, dopo
il quale si riparte dal primo e così via), o ping-pong, cioè si
parte dal primo fotogramma e si visualizzano in sequenza tutti gli altri, ma
quando si arriva all'ultimo si rivisualizzano tutti tornando indietro fino al
primo, per poi ripartire tornando "avanti", proprio come la pallina in
una partita di ping-pong.
In questo modo basta fare i fotogrammi del piccone
che va verso il basso, poi per farlo "risalire" basterà far
rivedere i fotogrammi all'indietro, dimezzando il numero di immagini gif
richieste.
Partendo da questa semplice applet si possono creare molte
animazioni con sonoro, interattive o meno, per abbellire e rendere più
singolare un sito web.
Facendo un ulteriore passo in avanti, è
possibile anche eseguire delle operazioni di distorsione, ondeggiamento ecc.
sulle immagini visualizzate, come potete vedere, ad esempio, nella mia home
page.
Fabio Ciucci
fabioc@anfiteatro.it
Scarica il listato 1: ANanim2b.java
Scarica il listato 2: ananim2b.html
Torna all' indice degli articoli