Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

ActionScript 2 vs ActionScript 3. Un confronto pratico

Si parla molto delle novità di Actionscript 3. Come cambierà il nostro modo di programmare in Flash?
Si parla molto delle novità di Actionscript 3. Come cambierà il nostro modo di programmare in Flash?
Link copiato negli appunti

Senza dubbio la novità più attesa nel panorama Flash è relativa all'introduzione, nella versione 9, del nuovo linguaggio ActionScript 3. Tale linguaggio è già utilizzabile in condizioni reali con Flex 2, ed è possibile sperimentarlo scaricando dagli Adobe Labs la "Flash 9 Professional ActionScript 3 Alpha".

Su questo linguaggio molto è stato scritto ponendo l'accento sulle nuove funzioni; in questo articolo cercheremo di essere più concreti, andando ad analizzare come cambierà il nostro codice con la nuova versione di questo linguaggio; lo faremo prendendo ad esempio alcuni snippet di utilizzo comune e ne analizzeremo la proposizione in ActionScript 2 e 3, cercando di evidenziare pro e contro dei diversi script.

Caricamento di immagini o swf esterni

ActionScript 2

Un'operazione che viene eseguita molto spesso dagli sviluppatori è il caricamento di un'immagine o di un filmato esterno. Con Flash Mx 2004 era stato introdotta la classe MovieClipLoader, che permette di caricare facilmente un elemento esterno e gestirne gli errori.

AS2: caricamento con MovieClipLoader e gestione errori

var container:MovieClip = createEmptyMovieClip("container", getNextHighestDepth());
var mcLoader:MovieClipLoader = new MovieClipLoader();
var loadListener:Object = new Object();
mcLoader.addListener(loadListener);
mcLoader.loadClip("Tramonto.jpg", container);

loadListener.onLoadError = function(target_mc:MovieClip, errorCode:String, httpStatus:Number) {
  trace(">> Errore");
  trace(">> ==========================");
  trace(">> Codice errore: " + errorCode);
  trace(">> Stato http: " + httpStatus);
}

loadListener.onLoadProgress = function(target:MovieClip, bytesLoaded:Number, bytesTotal:Number):Void {
  trace("Ho caricato " + bytesLoaded + " bytes su " + bytesTotal);
}

loadListener.onLoadStart = function ():Void {
  trace("Ho iniziato a caricare");
}

loadListener.onLoadComplete = function(mc:MovieClip):Void {
  trace("Ho caricato nel movieclip: " + mc);
}

Analizziamo i passaggi. Per prima cosa crea un nuovo movieclip sullo stage, che sarà il "contenitore" dell'immagine che andremo a caricare, quindi crea un oggetto movieClipLoader con nome "mcLoader". Questo sarà l'oggetto che useremo per applicare il comando loadClip, che permette di caricare la fonte esterna (swf, jpg, etc).

Abbiamo poi i "listener", ovvero degli oggetti che analizzano le operazioni: il nostro listener è loadListener, che creiamo con il comando new Object e andiamo poi ad associare all'oggetto MovieClipLoader creato in precedenza (mcLoader.addListener(loadListener). Infine abbiamo alcune funzioni associate a questo listener, precisamente:

  • onLoadError : intercetta eventuali errori (ad esempio se cerchiamo di caricare un file inesistente)
  • onLoadProgress: analizza il caricamento della fonte esterna e permette quindi di analizzare la quantità di dati caricati in ogni momento
  • onLoadStart: intercetta l'avvio del caricamento
  • onLoadComplete: intercetta la fine del caricamento (quindi quando abbiamo effettivamente a disposizione l'immagine nel nostro filmato).

Ad ciascun listener sono associat delle azioni che mostrano nel pannello "output" di Flash determinati messaggi. Utilizzando il file "CaricaJpg_AS2.fla" che troveremo nel file .zip allegato all'articolo potremo vedere questi listener in azione.

ActionScript 3

Per prima cosa, in AS3 la classe MovieClipLoader è stata sostituita dal package flash.display.Loader. Dobbiamo abituarci a questo fatto: quasi tutti i comandi AS1 e 2 sono stati sostituiti, rinominati o quantomeno spostati all'interno di altre classi in ActionScript 3. Questo potrebbe creare qualche problema per chi è abituato alle versioni precedenti; fortunatamente la Adobe ha messo a disposizione la ActionScript Migration guide che contiene tutti i cambiamenti e consentirà agli sviluppatori di individuare più rapidamente le novità introdotte.

Il metodo di assegnazione dei listener è simile, ma anch'esso è leggermente cambiato. Vediamo allora come riproporre in ActionScript 3 il codice visto in precedenza ed ottenere li stessi risultati.

AS3: caricamento con "flash.display.loader"

var loader:Loader = new Loader();
configureListeners(loader.contentLoaderInfo);
var request:URLRequest = new URLRequest("Tramonto.jpg");
loader.load(request);
addChild(loader);

function configureListeners(dispatcher:IEventDispatcher):void {
  dispatcher.addEventListener(Event.OPEN, openHandler);
  dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
  dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
  dispatcher.addEventListener(Event.COMPLETE, completeHandler);
}

function completeHandler(event:Event):void {
  trace("Ho finito di caricare");
}

function ioErrorHandler(event:IOErrorEvent):void {
  trace("ioErrorHandler: " + event.text);
}

function openHandler(event:Event):void {
  trace("openHandler: " + event);
}

function progressHandler(event:ProgressEvent):void {
  trace("Ho caricato " + event.bytesLoaded + " bytes su " + event.bytesTotal);
}

Il numero di righe di codice è quasi uguale, cambiano però diversi comandi. Come detto MovieClipLoader è sostituito da flash.display.loader, infatti creiamo un oggetto di questo tipo con il comando var loader:Loader = new Loader().

In secondo luogo, non possiamo più passare direttamente l'URL al comando load, ma dobbiamo utilizzare un oggetto URLRequest: teniamo presente questo aspetto, perché varrà per tutti i tipi di caricamento di dati esterni. Per questo motivo creiamo quindi un oggetto URLRequest (request) che poi passiamo al comando load.

La parte di caricamento si completa con l'inserimento del comando addChild. Questo comando "aggiunge" l'oggetto che verrà caricato allo stage, in modo che questo possa apparirvi: notiamo infatti che in questo codice non vi è la presenza del comando createEmptyMovieClip, che abbiamo invece dovuto usare in AS2 per impostare un "contenitore" per l'immagine caricata. Il riferimento da utilizzare per eventuali modifiche all'oggetto caricato quindi sarà loader, che è il nome dell'oggetto in cui abbiamo caricato l'immagine. Anche il comando addChild è da tenere a mente poiché dovremo utilizzarlo in molte occasioni.

Per caricare l'immagine basterebbe il codice che abbiamo analizzato, però vogliamo ottenere anche in questo caso maggiori informazioni: sull'avvio del caricamento, sullo stato di avanzamento del caricamento, sul completamento. Inoltre vogliamo intercettare eventuali errori.

Usiamo sempre dei listener, ma non li associamo con un comando tipo oggetto.addListener(listener), pittosto dobbiamo "aggiungerli" singolarmente con il comando addEventListener. Altra differenza da notare è che in questo caso non passiamo direttamente l'oggetto loader, ma utilizziamo loader.contentLoaderInfo: questa è una proprietà che contiene appunto le informazioni sull'oggetto loader e possiamo sfruttarla per assegnare i listener; questa proprietà contiene inoltre molte informazioni sulla fonte esterna che andiamo a caricare.

Poiché dobbiamo assegnare singolarmente i listener abbiamo creato una funzione (configureListener) che assegna le varie funzioni ai diversi listener, più precisamente:

  • openHandler viene assegnata ad Event.OPEN : è analogo al listener onLoadStart di ActionScript 2
  • ioErrorHandler viene assegnata a IOErrorEvent.IO_ERROR: è analogo al listener onLoadError
  • completeHandler viene assegnata ed Event.COMPLETE: è analogo al listener onLoadComplete
  • progressHandler viene assegnata a ProgressEvent.PROGRESS: è analogo al listener onLoadProgress

Vediamo quindi che i listener sono stati maggiormente suddivisi in categorie, quindi avremo eventi di caricamento (come OPEN e COMPLETE), eventi di errore input/output (IO_ERROR) ed eventi di avanzamento (come PROGRESS). In ActionScript 3 troviamo molti altri eventi: questa maggior suddivisione aiuta ad organizzare meglio il codice.

Lo stesso oggetto Loader offre diversi altri eventi che non analizziamo in questo articolo: il nostro scopo è confrontare brani di codice che forniscano le stesse funzionalità, inoltre i listener usati sono più che sufficienti per i classici caricamenti di immagini o filmati esterni.

Nota: gli esempi creati con ActionScript 3 richiedono la Flash 9 Public Alpha

Confrontiamo le due soluzioni

Un aspetto da tenere conto è la quantità di codice da scrivere: dover passare più tempo nella stesura del codice per ottenere una stessa soluzione può essere uno svantaggio per lo sviluppatore. In questo caso le righe di codice sono praticamente equivalenti (24 in ActionScript 2, 28 in ActionScript 3); anche a livello di dettagli forniti dai listener i due codici offrono risultati simili, in ActionScript 3 però abbiamo una miglior suddivisione dei listener stessi, inoltre questi offrono mediamente qualche informazione in più; da non sottovalutare poi la proprietà contentLoaderInfo che mantiene le informazioni sull'immagine caricata quali ad esempio url, larghezza, altezza, bytes caricati, bytes totali, eccetera: queste proprietà potrebbero tornare utili nel caso ad esempio modificassimo l'immagine caricata e volessimo poi riportarla alla sua situazione iniziale.

ActionScript 3 inoltre offre maggiori ampliamenti poiché i listener che mette a disposizione sono maggiori di quelli offerti dalla classe MovieClipLoader di AS2; sostanzialmente su un codice di questo tipo possiamo dire che le differenze sono poche ma abbastanza rilevanti, se dovessimo assegnare un risultato a questo confronto potremmo dire che AS3 vince ai punti, ma sostanzialmente le due soluzioni sono molto simili.

Caricamento di dati esterni

Rimaniamo nell'ambito del caricamento di risorse esterne, e dopo aver analizzato come inserire delle immagini (ricordiamo che il codice visto prima è valido anche per il caricamento di swf esterni) analizziamo le differenze tra le due versioni del linguaggio quando dall'esterno vogliamo caricare dei dati, provenienti ad esempio da un file di testo.

Codice in ActionScript 2

Da diverse versioni (precisamente da Flash Mx) è disponibile la classe loadVars, che permette l'invio e le ricezioni di dati con pagine server-side (ad esempio in PHP) o file di testo. Vediamo quindi come caricare dei dati da un file di testo esterno con ActionScript 2.

Per prima cosa creiamo un file di testo con nome "testo.txt", poi scriviamo il codice per leggerlo da Flash.

Contenuto del file "testo.txt"

testo=Testo esterno

Quindi all'interno di Flash scriviamo il seguente codice

AS2: Leggere un file di testo

var carica:LoadVars = new LoadVars();
carica.onLoad = function(success:Boolean) {
  if (success) {
    trace(this.testo);
  } else {
    trace("Errore nel caricamento del file.");
  }
};

carica.load("testo.txt");

Con questo codice creiamo un nuovo oggetto LoadVars (carica) e carichiamo il file "testo.txt" tramite il comando load. Se il caricamento va a buon fine (carica.onLoad), mostriamo il contenuto della variabile del file esterno, altrimenti mostriamo un errore.

Notiamo come la classe loadVars non permette l'utilizzo di listener, e anche la creazione di un preload presupporrebbe l'utilizzo di comandi come onEnterFrame o simili, dato che non è disponibile un listener che analizzi i progressi del caricamento.

Cosa cambia in ActionScript 3

AS3 in questo caso consente un grosso passo avanti: il procedimento utilizzabile infatti è simile a quello per il caricamento di un'immagine e sono disponibili tutti i listener. Non viene più utilizzata la classe loadVars, sostituita da flash.net.URLLoader, mentre gli altri passaggi sono analoghi a quelli visti per il caricamento di un'immagine; vediamo il codice.

AS3: Leggere un file di testo

// istanzia un oggetto URLLoader
var loader:URLLoader = new URLLoader();

// assegna al loader i gestori per gli eventi
configureListeners(loader);

// istanzia un oggetto URLRequest
var request:URLRequest = new URLRequest("testo.txt");

// richiama il metodo load() del loader per
// far partire il caricamento

loader.load(request);

function configureListeners(dispatcher:IEventDispatcher):void {
  dispatcher.addEventListener(Event.COMPLETE, completeHandler);
  dispatcher.addEventListener(Event.OPEN, openHandler);
  dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
  dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}

function completeHandler(event:Event):void {
  trace("Caricamento completato")
  var vars:URLVariables = new URLVariables(loader.data);
  trace(vars.testo);
}

function openHandler(event:Event):void {
  trace("Caricamento avviato");
}

function progressHandler(event:ProgressEvent):void {
  trace("Ho caricato " + event.bytesLoaded + " bytes di " + event.bytesTotal);
}

function ioErrorHandler(event:IOErrorEvent):void {
  trace("ioErrorHandler: " + event);
}

Il primo blocco di codice si occupa di creare un nuovo oggetto URLLoader (loader) e di impostare il relativo URLRequest (request), che ha come URL "testo.txt", ovvero il file che vogliamo caricare.

Nota: Nel caso dell'URLLoader è possibile passare ai listener direttamente l'oggetto, diversamente da quanto accade con la classe flash.display.loader. Questo perché non andiamo a caricare un elemento esterno con delle sue proprietà, per cui non è necessario un oggetto che tenga in memoria dati come altezza, larghezza e simili, ma ci basta ricevere le variabili per poterle elaborare e sfruttare in Flash; per lo stesso motivo non è presente il comando addChild: non dobbiamo posizionare nessun oggetto sullo stage, pertanto non è necessario tale comando.

Per quanto riguarda i listener possiamo fare riferimento a quanto visto nel caso precedente, l'unica differenza è nella funzione handlerComplete, dove abbiamo inserito il codice necessario per mostrare la variabile "testo" contenuta nel file esterno: creiamo un oggetto URLVariables (vars) con al suo interno i dati che sono stati caricati (loader.data), quindi grazie al comando trace mostriamo nel pannello di output il valore delle variabile "testo".

Confrontiamo le due soluzioni

In questo caso il confronto è nettamente a favore di ActionScript 3: la possibilità di sfruttare i listener anche nel caricamento di variabili ci permette di organizzare i nostri script senza dover utilizzare comandi che avviino cicli o simili, inoltre potremo gestire in modo molto più efficiente gli errori piuttosto che mostrare un generico messaggio all'utente. Il codice da scrivere è chiaramente maggiore ma in questo caso è tutto motivato dal gran numero di parametri controllabili; anche in questo caso abbiamo usato solo alcuni dei listener disponibili, dato che per il nostro scopo era sufficiente rilevare i passaggi "principali" del caricamento.

Fermare un caricamento

Flash 9 possiede un grosso vantaggio sia al caricamento delle immagini che dei dati, ovvero il comando close, che consente di arrestare il caricamento: fino alla versione 8 di Flash c'era questo problema: se un caricamento veniva avviato, poi non poteva essere interrotto finchè non fosse stato completato, e ciò portava spesso a caricamenti che proseguivano anche dopo che l'utente aveva abbandonato una determinata sezione del filmato, andando ad occupare banda e memoria; con il comando close sarà possibile terminare il caricamento ed ottimizzare quindi notevolmente le risorse.

Disegnare con i drawing methods

Introdotti in Flash Mx, i "drawing methods" si sono affermati piuttosto rapidamente data la possibilità da essi offerta di disegnare dinamicamente elementi sullo stage. Anch'essi sono stati modificati in AS3, ma soprattutto sono stati lievemente ampliati. Vediamo ad esempio come creare un rettangolo nei due linguaggi.

ActionScript 2

In ActionScript 2 è necessario creare un movieclip contenitore usando createMovieClip, quindi utilizzare determinate coordinate per il disegno, in questo modo

AS2: Disegno di un rettangolo

_root.createEmptyMovieClip("rect", 1);
with(rect){
  beginFill(0x000099, 80);
  lineStyle(1,0x000000, 100);
  lineTo(100, 0);
  lineTo(100, 50);
  lineTo(0, 50);
  lineTo(0, 0);
  endFill();
}

Con questo codice creiamo un nuovo movieclip (rect) e disegniamo un rettangolo largo 100 pixel e alto 50, con il bordo nero e lo sfondo blu con una trasparenza di 80.

Cosa cambia in ActionScript 3

Come accennato poco fa, in ActionScript 3 i drawing methods sono stati leggermente ampliati, e questo ampliamento consiste nell'inserimento di alcune funzioni già pronte per il disegno, quali:

  • drawRect
  • drawCircle
  • drawRoundRect
  • drawEllipse

Questo comporta che ad esempio per disegnare un rettangolo il codice diventa molto più semplice.

AS3: Disegno di un rettangolo

var disegno:MovieClip = new MovieClip();
with(disegno){
  graphics.beginFill(0x000099,0.8);
  graphics.lineStyle(1,0x000000,1.0);
  graphics.drawRect(0,0,100,50);
  graphics.endFill();
}
addChild(disegno);

Nota: il valore della trasparenza è più espresso con un valori da 0 a 100, ma da 0 a 1 (per cui per ottenere il risultato del valore 80 usato in ActionScript 2 andiamo ad utilizzare il valore 0.8 nel nostro script in ActionScript 3).

Un aspetto da ricordare è che mentre in Flash 8 bastava il nome dell'oggetto seguito dal drawing method desiderato, in Flash 9 dobbiamo inserire anche la voce graphics.

Se nel caso di un rettangolo i vantaggi dati dall'avere un metodo già pronto a disposizione possono sembrare tutto sommato relativi, proviamo i seguenti script.

AS3: Disegno di un rettangolo con angoli arrotondati

var disegno:MovieClip = new MovieClip();
with(disegno){
  graphics.beginFill(0x000099,0.8);
  graphics.lineStyle(1,0x000000,100);
  graphics.drawRoundRect(0,0,100,50,45);
  graphics.endFill();
}
addChild(disegno);

AS3: Disegno di un cerchio

var disegno:MovieClip = new MovieClip()
with(disegno){
  graphics.beginFill(0x000099, 0.8);
  graphics.lineStyle(1, 0x000000, 100);
  graphics.drawCircle(0, 0, 40);
  graphics.endFill()
}
addChild(disegno);

Conforontiamo quest'ultimo esempio con il codice riportato nella guida di Flash 8 come esempio per il disegno di un cerchio.

AS2: Disegno di un cerchio

this.createEmptyMovieClip("circle2_mc", 2);
circle2_mc.lineStyle(0, 0x000000);
drawCircle(circle2_mc, 100, 100, 100);

function drawCircle(mc:MovieClip, x:Number, y:Number, r:Number):Void {
  mc.moveTo(x+r, y);
  mc.curveTo(r+x, Math.tan(Math.PI/8)*r+y, Math.sin(Math.PI/4)*r+x, Math.sin(Math.PI/4)*r+y);
  mc.curveTo(Math.tan(Math.PI/8)*r+x, r+y, x, r+y);
  mc.curveTo(-Math.tan(Math.PI/8)*r+x, r+y, -Math.sin(Math.PI/4)*r+x, Math.sin(Math.PI/4)*r+y);
  mc.curveTo(-r+x, Math.tan(Math.PI/8)*r+y, -r+x, y);
  mc.curveTo(-r+x, -Math.tan(Math.PI/8)*r+y, -Math.sin(Math.PI/4)*r+x, -Math.sin(Math.PI/4)*r+y);
  mc.curveTo(-Math.tan(Math.PI/8)*r+x, -r+y, x, -r+y);
  mc.curveTo(Math.tan(Math.PI/8)*r+x, -r+y, Math.sin(Math.PI/4)*r+x, -Math.sin(Math.PI/4)*r+y);
  mc.curveTo(r+x, -Math.tan(Math.PI/8)*r+y, r+x, y);
}

Una bella differenza! Possiamo quindi affermare che, sotto l'aspetto del disegno, Flash 9 sia di gran lunga superiore a Flash 8, poiché ci da la possibilità di creare forme geometriche "basilari" in maniera molto più rapida! Chiaramente per quanto riguarda forme più complesse non ci sono particolari differenze a livello di stesura del codice.

Conclusioni

ActionScript 3 porta delle modifiche (e in alcuni casi dei vantaggi) nella realizzazione di script piuttosto comuni. Il processo di apprendimento del nuovo linguaggio, considerando il fatto che praticamente tutti i comandi sono stati spostati, rinominati o in alcuni casi addirittura rimossi, potrebbe non essere molto comodo per alcuni utenti che non hanno il tempo di approfondire le novità.

La migration guide risulta un valido aiuto, non sempre però è chiara. Ad esempio in AS3 è stato rimosso il comando duplicateMovieClip, e la migration guide non spiega bene come sostituirlo, anzi finora le soluzioni a tale problema le troviamo solo sul Kirupa Forum. Sullo stesso forum è possibile trovare alcuni interessanti script che "rimediano" alle differenze di comportamento di AS3 rispetto ad AS2.

Insomma non è tutto rose e fiori, per quanto il nuovo linguaggio porti sicuramente delle novità interessanti anche negli script di utilizzo comune, i flasher "di vecchia data" dovranno adeguarsi; probabilmente più semplice risulterà l'apprendimento del linguaggio per chi inizierà ad utilizzare il software proprio con la versione 9, dato che comincerà da zero e apprenderà direttamente la logica di AS3 piuttosto di dover "cambiare" quanto ha imparato in precedenza.

Il processo di cambiamento però non sarà immediato. Il Flash Player (oggi alla versione 9) supporta ancora bene anche il "vecchio" codice AS2 ed i flasher sono abbastanza allenati alle mutazioni del linguaggio.

Ti consigliamo anche