Album fotografico 3d in AS3 - parte seconda

Autorer: admin
29 Settembre 2008

Riprendiamo in mano il vecchio progetto della “Galleria fotografica 3D in Actionscript 3″.
Come promesso verranno ora implementate determinate caratteristiche, al fine di migliorarne l’aspetto estetico.

Il risultato che vogliamo raggiungere questa volta è qui presentato.

Come vede sono state aggiunte delle cosette:
-    sono stati aggiunti degli elementi sonori (avremmo potuto aggiungere uno sfondo musicale, la tecnica è uguale, ma sarebbe stato eccessivo per i miei gusti).
-    Durante lo zoom è pure possibile muovere le foto in 3D.
-    Durante lo zoom, cliccando con le frecce della tastiera, si ci sposta fra le immagini.

Si tratta di piccole aggiunte che rendono più gradevole il filmato.
Faccio una premessa: i metodi per arrivare a questo risultato sono più di 1, quindi qualche altro programmatore avrebbe potuto fare diversamente da me, anche più velocemente, ma l’importante è sempre arrivare ad un risultato funzionale e gradevole.

Allora, cominciamo col tutorial.
Il modo migliore per vedere le aggiunte rispetto al codice precedente è quello di confrontare i 2 file .as che sono inclusi nel progetto (ossia quello iniziale e quello finale). Il confronto può essere fatto facilmente col software “FlashDevelop” che permette la visualizzazione dei 2 codici in 2 colonne diverse: basta aprire il primo file “principale.as” e poi trascinare al centro l’altro file .as, verrà così data la possibilità d’indicare in quale spazio si vuole aprire il nuovo file, senza chiudere quello precedente.

Le prime differenze riguardano i “package” che vengono importati all’inizio.

//importare i package necessari per i controlli della tastiera, il
//1° indica gli eventi collegati alla tastiera, il 2° i relativi pulsanti.
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;

//importare i package per controllare una sequenza di tempo (un po’
//come fosse un contatore) e gli eventi correlati.
import flash.utils.Timer;
import flash.events.TimerEvent;

//importare i package per il controllo del suono da caricare dinamicamente
import flash.media.Sound;

La successiva differenza appare nella zona d’inserimento delle variabili, sono aggiunti:

//saranno utili per definire le coordinate delle varie immagini.
private var oggetto_3d_x_foto_centro:Number = new Number;
private var oggetto_3d_y_foto_centro:Number = new Number;

Aggiungere gli effetti sonori.

Analizziamo ora gli extra-code per obiettivi, ossia vediamo quale codice aggiungere per includere il suono (dopo che abbiamo importato il package “sound”). Innanzitutto ci bisognano 3 file .mp3 per i suoni che vogliamo associare agli eventi (nel progetto sono stati inseriti 3 generici suoni, scaricabili gratuitamente su www.html.it, ottimo sito per web designer), questi devono essere inseriti all’interno della stessa cartella dove risiede il nostro file sorgente .fla, su cui stiamo lavorando. Il nostro compito sarà di comunicare a Flash, tramite AS3, di leggere il file esterno e riprodurlo ad una precisa occasione.
Il codice che verrà presentato dispone di elementi nuovi ed altri già esistenti nel vecchio file (stiamo soltanto aggiungendo del codice a quello vecchio), quindi differenzierò visivamente il nuovo codice da quello già esistente (la presenza di quest’ultimo è però necessario per capire dove stiamo intervenendo, in quale precisa area) che è in corsivo.

private function onOver(evento_mouse:MouseEvent):void {
if (evento_mouse.target is Sprite3D && !modalita_zoom) {
(evento_mouse.target as Sprite3D).transform.colorTransform = colore_chiaro;

//lettura file click.mp3
//La richiesta URL è necessaria per richiamare il file esterno (sia che si
//trovi su Internet, es. http://www.enricoviola.it/blog/esempio.mp3, sia nel
//proprio pc, indicando o l’indirizzo assoluto o quello relativo al file di flash,
//come in questo caso.
var richiesta_file:URLRequest = new URLRequest(”click.mp3″);

//realizzazione dell’oggetto “sound”, il suo caricamento (indicando la variabile
//definita per “URLRequest” e non il file direttamente) e il suo avviamento.
var suono:Sound = new Sound();
suono.load(richiesta_file);
suono.play();
}
}

La stessa cosa andrà fatta per il altri 2 suoni, al click:

private function onClick(evento_mouse:MouseEvent):void {
var oggetto_3d:Object;

//lettura file suono mp3
var richiesta_file_mov:URLRequest = new URLRequest(”suono_mov.mp3″);
var suono_mov:Sound = new Sound();
suono_mov.load(richiesta_file_mov);
suono_mov.play();

….. (ossia continua il codice)

ed allo spostamento con le freccie:

private function spostamento_da_zoom(evento_tastiera:KeyboardEvent) {

//lettura file suono mp3
var richiesta_file_mov:URLRequest = new URLRequest(”suono_freccia.mp3″);
var suono_mov:Sound = new Sound();
suono_mov.load(richiesta_file_mov);
suono_mov.play();
…..

Con queste semplicissime aggiunte abbiamo inserito i nostri effetti sonori.

Aggiungere il movimento tridimensionale anche durante lo zoom.

La difficoltà che ho riscontrato in questo caso riguarda il problema di evitare che lo spostamento tridimensionale si applichi anche mentre si effettua il movimento dell’album in avanti o indietro.
Infatti tale movimento dura precisamente 0.3 secondi; ma se non comunichiamo, via AS3, che in quell’intervallo si deve bloccare temporaneamente il movimento 3D, il risultato risulta sgradevole ed illogico, bloccando di fatto l’avanzamento o l’arretramento dell’album.

Purtroppo, ogni programmatore deve convincersi che anche le cose, per noi umani, più facili posso essere assurde per una macchina, e che vanno considerati ogni minimo dettaglio per la programmazione (cose che vi faranno mettere le mani in testa, ma non preoccupatevi, se sapete come fare risulta tutto veloce, semplice e, soprattutto principale motivo di tanto esercizio, gratificante.

private function onClick(evento_mouse:MouseEvent):void {
var oggetto_3d:Object;
……..

if (evento_mouse.target is Sprite3D && !modalita_zoom) {
foto_zoomata = evento_mouse.target as Sprite3D;

//memorizziamo le coordinate X e Y del mouse, al momento del click
oggetto_3d_x_foto_centro = (evento_mouse.target.x);
oggetto_3d_y_foto_centro = (evento_mouse.target.y);

//modifichiamo la luminosità delle foto e dell’album per lo zoom
foto_zoomata.transform.colorTransform = colore_scuro;
album.transform.colorTransform = new ColorTransform(1.2, 1.2, 1.2, 1, 0, 0, 0, 0);

oggetto_3d = new Object();
oggetto_3d.z = 0;
oggetto_3d.rotationX = 0;
oggetto_3d.rotationY = 0;
oggetto_3d.x = 0 - evento_mouse.target.x;
oggetto_3d.y = 0 - evento_mouse.target.y;
oggetto_3d.ease = Sine.easeInOut;
TweenLite.to(album, .6, oggetto_3d);
modalita_zoom = true;

//definiamo un contatore temporale, la classe Timer richiede 2 valori:
//il tempo, in millisecondi, di durata della sequenza temporale (in questo
//caso 0.61 secondi, un po’ di più del movimento in avanti dell’ album,
// indicato nella funzione “TweenLite.to” ) e il numero di ripetizioni (in
//questo caso 1 sola) della stessa sequenza.
var tempo_zoom:Timer = new Timer(610, 1);
tempo_zoom.start(); //avviamo il contatore
//indichiamo, con la classe “TimerEvent”, che a conclusione della sequenza
//(ossia dopo i 0.61 sec.) di avviare la funzione “zoomato”.
tempo_zoom.addEventListener(TimerEvent.TIMER_COMPLETE, zommato);
}


//nel caso in cui clicchiamo per tornare al livello di zoom iniziale
else if (modalita_zoom) {

//rimuovi il listerner riguardante il movimento tridimensionale dell’album
//mentre questo era zoomato, è fondamentale togliere il listener per
//evitare che, durante l’arretramento dello zoom dell’album, possa
//bloccarsi quest’ultimo al primo leggero movimento del mouse.
stage.removeEventListener(MouseEvent.MOUSE_MOVE, muovi_album_zoom);

//reimpostiamo l’esatta luminosità all’album
album.transform.colorTransform = new ColorTransform(1, 1, 1, 1, 0, 0, 0, 0);

oggetto_3d = new Object();
oggetto_3d.z = profondita_z;
oggetto_3d.x = 0;
oggetto_3d.y = 0;
oggetto_3d.ease = Sine.easeOut;
TweenLite.to(album, .3, oggetto_3d);

//avviamo un nuovo contatore (che si ripete solo 1 volta), per indicare
//che dopo 0.61 sec dal click dobbiamo attivare la funzione “ritorno_normale”.
var tempo_ritorno:Timer = new Timer(610, 1);
tempo_ritorno.start();
tempo_ritorno.addEventListener(TimerEvent.TIMER_COMPLETE, ritorno_normale);
}
}

Per completare l’aggiunta tridimensionale dobbiamo scrivere altre 3 funzioni, posizionandole dopo la chiusura della funzione precedente “onClick”.

//funzione “zoomato” che si attiva alla conclusione della prima sequenza
// temporale, attivata al click per zoomare in avanti.
private function zommato(evento_tempo:TimerEvent) {
stage.addEventListener(MouseEvent.MOUSE_MOVE, muovi_album_zoom);
}

//funzione “muovi_album_zoom” che si attiva mentre l’album è zoomato in
//avanti ed ad ogni movimento del mouse, questo listener viene rimosso nel
//si effettui un altro click sull’album (per ritornare alla modalità non zoom).
private function muovi_album_zoom(evento_mouse_zoom:MouseEvent) {

//ci ricalcoliamo le coordinate del mouse, in modo da spostare l’album
//in tridimensionale secondo la direzione del mouse.
var mouseXPos:Number = (evento_mouse_zoom.stageX - stage.stageWidth / 2) / (stage.stageWidth / 2);
var mouseYPos:Number = (evento_mouse_zoom.stageY - stage.stageHeight / 2) / (stage.stageHeight / 2);
var oggetto_3d:Object = new Object();
oggetto_3d.rotationY = 45 * mouseXPos;
oggetto_3d.rotationX = -15 * mouseYPos;

//in questo caso comincia ad esserci utili le variabili “oggetto_3d_x_foto_centro”
//che definiscono il centro delle foto nello spazio 3D,
//al fine di definire in questo caso un movimento tridimensionale uguale
//a quello presente quando l’album non è zoomato.
oggetto_3d.x = (50 * mouseXPos) - oggetto_3d_x_foto_centro;
oggetto_3d.y = (50 * mouseYPos) - oggetto_3d_y_foto_centro;
oggetto_3d.ease = Sine.easeOut;
TweenLite.to(album, .3, oggetto_3d);
}

//funzione attivata alla fine della seconda sequenza temporale, quando
//vogliamo ritornare alla modalità non zoom dell’album, e interviene
//nella definizione della precedente funzione “onClick”.
private function ritorno_normale(evento_tempo_ritorno:TimerEvent) {
modalita_zoom = false;
}

Aggiunta spostamento fra le foto, con le frecce della tastiera.

Per ultimo aggiungiamo questo effetto per spostarci fra le foto, sia che ci troviamo in modalità zoom che in modalità normale.
Questa funzione può essere inserita subito dopo di quella “ritorno_normale”.

//inseriamo il listener accanto a tutti gli altri listener, presenti nella

//funzione “costruzione album”.

stage.addEventListener(KeyboardEvent.KEY_DOWN, spostamento_da_zoom);

….

//la funzione viene attivata alla pressione di un tasto della tastiera
//ovviamente l’effetto funzionerà solo nel caso in cui vengano
//premuti i tasti delle frecce.
private function spostamento_da_zoom(evento_tastiera:KeyboardEvent) {

//lettura file suono mp3
var richiesta_file_mov:URLRequest = new URLRequest(”suono_freccia.mp3″);
var suono_mov:Sound = new Sound();
suono_mov.load(richiesta_file_mov);
suono_mov.play();

var oggetto_3d_1:Object = new Object();

//i seguenti controlli “if” servono per verificare l’effettiva posizione della
//foto visualizzata (centrata momentaneamente nell’album).
if(album.y>100){
var y_precedente:Number = 360; }
if(album.y<-100){
var y_precedente:Number = -360; }
if(album.y<100 && album.y>-100){
var y_precedente:Number = 0; }
if(album.x>100){
var x_precedente:Number = 510; }
if(album.x<-100){
var x_precedente:Number = -510; }
if(album.x<100 && album.x>-100){
var x_precedente:Number = 0; }

//Con questa funzione si controlla se il tasto premuto è una freccia,
//il comando “switch” funzione un po’ come l’istruzione “if”, ossia se
//il caso (”case”) è vero allora attiva la funzione successiva fino al comando
//”break” (obbligatorio l’inserimento) che fa uscire dall’istruzione.
//Il comando “keyCode” invece, appartenente al package “KeyboardEvent”, indica
//il valore del tasto premuto.
switch(evento_tastiera.keyCode){

//si realizza quindi il controllo del “keyCode” per verificare se è la freccia
case Keyboard.DOWN:

//il controllo “if” in questo caso serve per verificare che non ci
//troviamo sulla foto più bassa (perché altrimenti scenderemo ancora
//più sotto inutilmente). Ovviamente la foto più bassa ha una coordinata
//Y inferiore < a -350 (precisamente si trova a -360), quindi se la foto
//selezionata (ossia centrata nell’album) è proprio quella inserita nella riga
//inferiore, allora non permettiamo alla pressione della freccia SOTTO
//di poter scendere ancora di più, semplicemente non succede niente.
if (y_precedente > -350)
{

//indichiamo che lo spostamento, rispetto alla coordinata verticale
//precedente, deve essere di -360 px.
oggetto_3d_1.y = y_precedente - 360;
oggetto_3d_1.ease = Sine.easeOut;
TweenLite.to(album, .3, oggetto_3d_1);
oggetto_3d_y_foto_centro = - oggetto_3d_1.y;
}
break;

//I restanti altri pulsanti funzionano con lo stesso criterio.
case Keyboard.UP:
if (y_precedente < 350)
{
oggetto_3d_1.y = y_precedente + 360;
oggetto_3d_1.ease = Sine.easeOut;
TweenLite.to(album, .3, oggetto_3d_1);
oggetto_3d_y_foto_centro = - oggetto_3d_1.y;
}
break;

//Per lo spostamento orizzontale cambiamo le misure in pixel di moviemento
//ma si utilizza lo stesso ragionamento per ogni freccia.
case Keyboard.LEFT:
if (x_precedente < 500)
{
oggetto_3d_1.x = x_precedente + 510;
oggetto_3d_1.ease = Sine.easeOut;
TweenLite.to(album, .3, oggetto_3d_1);
oggetto_3d_x_foto_centro = - oggetto_3d_1.x;
}
break;
case Keyboard.RIGHT:
if (x_precedente > -500)
{
oggetto_3d_1.x = x_precedente - 510;
oggetto_3d_1.ease = Sine.easeOut;
TweenLite.to(album, .3, oggetto_3d_1);
oggetto_3d_x_foto_centro = - oggetto_3d_1.x;
}
break;
}
}

Quest’ultimo codice risulta un po’ complesso in alcuni punti, ma poi procede sempre allo stesso modo. Anche la modalità con cui sono arrivato ala definizione di questo spostamento con le frecce, può differire in altri progetti, ossia si può arrivare allo stesso risultato in più modi.

Ora il nostro progetto appare sempre più completo ed approfondito, con un impatto estetico maggiore.

Spero in futuro di implementare ancora il progetto e presentare un altro tutorial in AS3.

;-) Fate sempre ritorno!!! Byyyyyyyye

sorgenti file del secondo progetto

Leave a Reply