La classe BitmapData permette una notevole manipolazione di immagini e movieclip; ne abbiamo già visto le potenzialità in "Dividere un'immagine con Actionscript 3".
In questo articolo sfrutteremo ancora una volta la classe BitmapData e utilizzeremo anche parte del codice dell'articolo citato, questa volta per creare un effetto di "esplosione" su un movieclip. L'utilizzo di Actionscript non è comunque l'unico modo per ottenere tale effetto, infatti da Flash Mx 2004 sono disponibili i cosidetti "Effetti della timeline", ovvero degli effetti predefiniti disponibili in Flash che in pratica creano automaticamente, in base ad alcuni parametri, determinate animazioni; uno di questi effetti è proprio Explode.
Esplosione di un movieclip con l'effetto da timeline
Per utilizzare l'effetto da timeline è necessario creare un movieclip sullo stage.
Una volta importata l'immagine nel nostro filmato possiamo convertirla in movieclip. A questo punto possiamo applicare il nostro effetto: dal menu Insert selezioniamo Timeline Effects, quindi Effects e infine Explode.
La prima opzione rigarda la durata dell'effetto, espressa in fotogrammi: usando i timeline effect infatti otteniamo una o più interpolazioni, per cui una volta applicato l'effetto avremo diversi fotogrammi sulla linea temporale, in questo caso ognuno corrispondente a un "frammento" del movieclip "esploso".
La seconda opzione è la direzione: possiamo scegliere quindi la direzione di movimento dei pezzi dopo l'esplosione, l'Arc Size stabilisce invece l'area utilizzata per dividere l'immagine in pezzi.
Possiamo ruotare i frammenti grazie all'opzione Rotate Fragments, espressa in gradi, inoltre possiamo cambiarne la dimensione durante il movimento sia per quanto riguarda l'asse orizzontale che quello verticale. Queste ultime due impostazioni saranno l'impressione della forza dell'esplosione poiché frammenti più grandi sembreranno "avvicinarsi" di più all'utente.
Ultima opzione è la trasparenza finale dei segmenti, che normalmente viene impostata a zero (come da valore predefinito).
Ad ogni cambio di una o più opzioni sarà necessario premere il tasto Update preview (in alto a destra) per aggiornare la finestra di anteprima con l'effetto.
Una volta settate le nostre preferenze possiamo premere il tasto Ok e attenere l'elaborazione dell'effetto; alla fine avremo sulla timeline un numero di fotogrammi pari alla durata dell'effetto e soprattutto nella libreria potremo vedere una cartella Effects Folder e un movieclip Explode 1; la cartella contiene il disegno di tutti i "tasselli" che formano l'esplosione, mentre il movieclip contiene l'animazione vera e propria.
Risultato ottenuto con l'effetto Explode
L'effetto è piuttosto d'impatto, tuttavia trattandosi di un'interpolazione e trovandoci con una grande quantità di clip, applicare modifiche o personalizzazioni all'effetto risulta piuttosto difficile, inoltre per quanto le varie parti dell'esplosione siano create automaticamente da Flash si tratta di fatto di oggetti vettoriali con tutto quanto ne consegue in termini di peso.
Esplosione di un movieclip con Actionscript 3
Come abbiamo anticipato, riutilizzeremo pressoché tutto il codice visto per la divisione delle immagini, questo perché come abbiamo visto il primo passaggio per creare l'effetto di esplosione è dividere l'immagine originale in più clip. L'unica variazione rispetto al codice visto nel precedente articolo sarà sul posizionamento dei tasselli: se nel caso della divisione avevamo disposto i vari pezzi in maniera casuale, questa volta inizialmente li lasceremo alle coordinate originali, inoltre renderemo pubbliche le variabili inerenti il numero di tasselli.
Ecco quindi il codice completo della classe dividi.as.:
Listato 1. Divide l'immagine
package{
// importiamo il package flash.display
import flash.display.*;
// importiamo il package flash.geom
import flash.geom.*
// importiamo il package flash.events
import flash.events.*
// importiamo il comando URLRequest del package flash.net
import flash.net.URLRequest
public class dividi extends MovieClip {
// Impostiamo le variabili per il numero di tasselli
private var pezzi_h:uint
private var pezzi_v:uint
// Creiamo lo sprite dove mostreremo i tasselli
var sprite_tasselli:Sprite = new Sprite();
public function imposta_divisione(quale:String,po:uint,pv:uint):void{
// impostiamo il numero di pezzi orizzontali
pezzi_h = po
// impostiamo il numero di pezzi verticali
pezzi_v = pv
var carica_foto:Loader = new Loader()
var richiesta:URLRequest = new URLRequest(quale)
carica_foto.contentLoaderInfo.addEventListener(Event.COMPLETE,dividi_foto)
carica_foto.load(richiesta)
}
public function dividi_foto(chi:Event):void{
// creiamo una copia dell'immagine
var immagine:Bitmap = Bitmap(chi.target.loader.content);
// stabiliamo larghezza e altezza di ogni pezzo
var l_pezzo = Math.floor(immagine.width/pezzi_h)
var a_pezzo = Math.floor(immagine.height/pezzi_v)
// tagliamo i vari pezzi
for(var r:uint=0;r<pezzi_h;r++){ // percorriamo tutte le righe
for(var c:uint=0;c<pezzi_v;c++){ // e tutte le colonne
// creiamo una bitmap con le dimensioni del pezzo del puzzle
var img_pezzo:Bitmap = new Bitmap(new BitmapData(l_pezzo,a_pezzo));
// copiamo i pixel dall'immagine originale al pezzo creato
img_pezzo.bitmapData.copyPixels(immagine.bitmapData,new Rectangle(r*l_pezzo,c*a_pezzo,l_pezzo,a_pezzo),new Point(0,0));
// creiamo un nuovo sprite
var sprite_pezzo:Sprite = new Sprite();
sprite_pezzo.x = r*l_pezzo
sprite_pezzo.y = c*a_pezzo
// inseriamo nello sprite la bitmap creata
sprite_pezzo.addChild(img_pezzo);
// inseriamo lo sprite "sprite_pezzo" dentro a "sprite_tasselli"
sprite_tasselli.addChild(sprite_pezzo)
}
}
// aggiungiamo sprite_tasselli allo stage
addChild(sprite_tasselli)
}
}
}
Con questo codice siamo in grado di dividere un'immagine in un numero di tasselli stabilito dai parametri po (pezzi orizzontali) e pv (pezzi verticali); il parametro quale stabilisce invece l'immagine (caricabile esternamente che verrà divisa in parti.
Il nostro scopo è quello di far esplodere la clip, quindi creeremo la classe esplodi che estenderà la classe dividi:
Listato 2. Esplode l'immagine
package{
// importiamo il package flash.display
import flash.display.*;
// importiamo il package flash.events
import flash.events.* public class esplodi extends dividi {
private var totale_pezzi = Number
public function imposta(quale:String,po:uint,pv:uint):void{
imposta_divisione(quale,po,pv)
totale_pezzi = po*pv
}
}
}
Associamo come Document class, al nostro FLA, la classe esplodi, quindi inseriamo il seguente codice Actionscript sul primo fotogramma:
imposta("Icona.png",8,8)
Icona.png è l'immagine da caricare e verrà divisa in 64 parti (8 righe da 8 colonne ciascuna). A questo punto non ci resta che impostare l'animazione dei tasselli: operando via codice possiamo decidere per una direzione "fissa" oppure impostare il tutto in maniera più casuale.
Per questo scopo è molto utile la classe Tween di Actionscript, che ci permette di impostare facilmente dei movimenti tramite codice: basterà impostare l'oggetto su cui vogliamo agire, la proprietà che voriamo variare, il valore iniziale, quello finale e la durata dell'animazione.
Per creare un'esplosione con direzione in basso e a destra, con i pezzi che diventano trasparenti, possiamo usare il seguente codice:
Listato 3. Esplosione con direzione in alto e basso
public function avvia_esplosione(evt:MouseEvent){
for(var n=0; n<totale_pezzi; n++){
var act_sprite = sprite_tasselli.getChildAt(n)
var TweenX:Tween = new Tween(act_sprite, "x", None.easeNone, act_sprite.x, act_sprite.x+(Math.random()*200), 1, true);
var TweenY:Tween = new Tween(act_sprite, "y", None.easeNone, act_sprite.y, act_sprite.y+(Math.random()*200), 1, true);
var TweenXscale:Tween = new Tween(act_sprite, "scaleX", None.easeNone, act_sprite.scaleX, act_sprite.scaleX*4, 1, true);
var TweenYscale:Tween = new Tween(act_sprite, "scaleY", None.easeNone, act_sprite.scaleY, act_sprite.scaleY*4, 1, true);
var TweenA:Tween = new Tween(act_sprite, "alpha", None.easeNone, 1, 0, 1, true);
}
}
I parametri dei diversi comandi Tween indicano rispettivamente l'oggetto su cui eseguire il movimento, la proprietà da variare, l'eventuale easing, il valore iniziale della proprietà selezionate, il valore finale, la durata dell'animazione e l'utilizzo dei secondi (true) o dei frame. Nel nostro caso modifichiamo l'oggetto sprite_act, ricavato dallo sprite sprite_tasselli grazie al metodo getChildAt
(Gestione della profondità in AS3) e ne variamo la posizione, la trasparenza (alpha) e le dimensioni (scaleX e scaleY), il tutto per la durata di 1 secondo (1,true). Impostando l'ultimo parametro su false potremo invece basare la durata dell'animazione sui fotogrammi.
Torniamo nel FLA e inseriamo questa riga di codice:
stage.addEventListener(MouseEvent.CLICK,avvia_esplosione)
A questo punto, testando il filmato, ci basterà cliccare sullo stage per far spostare i pezzi, si muoveranno tutti verso il basso e verso destra, ingrandendosi e diventano trasparenti:
Risultato ottenuto tramite Actionscript
Per fare in modo che l'esplosione non avvenga solo in una direzione ma che i tasselli si "spargano" maggiormente possiamo cambiare i valori per TweenX e TweenY in questo modo:
var TweenX:Tween = new Tween(act_sprite, "x", None.easeNone, act_sprite.x, act_sprite.x+(Math.random()*200-100), 1, true);
var TweenY:Tween = new Tween(act_sprite, "y", None.easeNone, act_sprite.y, act_sprite.y+(Math.random()*200-100), 1, true);
Potrebbe essere utile parametrizzare almeno la durata dell'animazione, quindi potremmo modificare la nostra classe in questo modo:
Listato 4. Parametrizza la durata dell'animazione
package{
// importiamo il package flash.display
import flash.display.*;
// importiamo il package flash.events
import flash.events.*
// importiamo i package per le tween
import fl.transitions.Tween;
import fl.transitions.easing.*
public class esplodi extends dividi {
private var totale_pezzi:Number
private var durata:Number
public function imposta(quale:String,po:uint,pv:uint):void{
imposta_divisione(quale,po,pv)
totale_pezzi = po*pv
}
public function avvia_esplosione(evt:MouseEvent){
for(var n=0; n<totale_pezzi; n++){
var act_sprite = sprite_tasselli.getChildAt(n)
var TweenX:Tween = new Tween(act_sprite, "x", None.easeNone, act_sprite.x, act_sprite.x+(Math.random()*300-150), durata, true);
var TweenY:Tween = new Tween(act_sprite, "y", None.easeNone, act_sprite.y, act_sprite.y+(Math.random()*300-150), durata, true);
var TweenXscale:Tween = new Tween(act_sprite, "scaleX", None.easeNone, act_sprite.scaleX, act_sprite.scaleX*4, durata, true)
var TweenYscale:Tween = new Tween(act_sprite, "scaleY", None.easeNone, act_sprite.scaleY, act_sprite.scaleY*4, durata, true)
var TweenA:Tween = new Tween(act_sprite, "alpha", None.easeNone, 1, 0, durata, true)
var TweenR:Tween = new Tween(act_sprite,"rotation",None.easeNone,0,60, durata,true)
}
}
}
}
A questo punto dal nostro FLA possiamo variare la durata dell'animazione in questo modo:
Listato 5. Varia la durata dell'animazione
imposta("icona.png",8,8)
durata = 0.5
sprite_tasselli.x = 100
sprite_tasselli.y = 100
stage.addEventListener(MouseEvent.CLICK,avvia_esplosione)
Otterremo così il seguente risultato:
Risultato con la durata impostata a 0.5 e direzioni maggiormente casuali
Nel nostro esempio abbiamo usato le classi Tween offerte da Flash, tuttavia è possibile utilizzare delle classi esterne come ad esempio TweenLite, che hanno come vantaggio un minor peso e soprattutto performance solitamente migliori delle tween incorporate in Actionscript. Questo costituisce ovviamente un notevole vantaggio poiché potremmo utilizzare più tasselli senza avere eccessivi rallentamenti, per esempio dividendo l'immagine del nostro esempio in 256 tasselli (16x16) le Tween di Flash cominciano a non eseguire correttamente l'effetto, mentre la TweenLite non da problemi nemmeno con maggiori divisioni come ad esempio una da 625 tasselli (25x25) che possiamo vedere di seguito:
Utilizzo della classe TweenLite per una versione con 625 tasselli
Qualora provassimo a utilizzare 625 tasselli con le normali Tween l'effetto non funzionerebbe correttamente.
Versione da 625 tasselli con le normali Tween di Flash