È il primo compleanno di ActiveTuts +! Festeggiamo realizzando un biglietto di auguri musicale in 3D con Papervision3D e TweenMax.
Inizia creando una nuova cartella (questa sarà la cartella principale del tuo progetto) e crea un nuovo FLA AS3 all'interno di quella cartella, chiamato Main.fla. Questo conterrà tutta l'interfaccia utente di cui abbiamo bisogno per creare la scheda.
Per questo tutorial avremo bisogno di due popolari librerie Flash: Papervision3D e TweenMax. Scarica Papervision (sto usando la versione 2.1.932) ed estrai il com e nochump cartelle dallo zip alla cartella principale del progetto. Scarica TweenMax (sto usando la versione 11) ed estrai anche lo zip nella cartella principale del tuo progetto.
Ora crea un file AS vuoto; salvalo come "CardViewport.as" nella cartella principale del tuo progetto. Questa sarà la nostra finestra di papervision3d contenente la scheda. Crea un altro file AS vuoto, nella stessa cartella, chiamato "Main.as." Questa sarà la tua classe di documenti. (Non sai come usare una classe di documenti? Leggi questa breve introduzione.)
La struttura della tua cartella dovrebbe assomigliare a questa:
Apri Main.fla e modifica il livello per renderlo 500x440 con una frequenza fotogrammi di 30 fps. Imposta la classe del documento su Principale:
Abbiamo solo bisogno di due livelli per questo tutorial:
Nel livello viewport crea una forma rettangolare. Adattalo alle dimensioni del palco e spostalo sulla posizione 0,0. Premi F8 per convertire la forma in un simbolo MovieClip. Seleziona la casella da esportare per ActionScript e aggiungi il nome della classe CardViewport. Si collegherà alla classe che costruiremo in seguito.
Ora fai clic su viewport movieClip e assegnagli un nome di istanza di "viewport".
Aprire il simbolo del clip filmato della vista e creare lo sfondo desiderato. Questo è quello che ho fatto: un paio di forme sfumate, una per il cielo e una per il terreno e il logo ActiveTuts + centrato sul cielo.
Sul livello del pulsante crea una forma rettangolare. Convertirlo in un simbolo di clip filmato e chiamarlo "open_mc"; assicurati di dargli lo stesso nome di istanza.
All'interno di open_mc crea un campo di testo. Impostalo come dinamico, assegnagli un nome di istanza di label_txt e incorpora i caratteri facendo clic su "Incorporamento caratteri" e selezionando l'alfabeto che desideri utilizzare.
Fallo sembrare come vuoi. Ho costruito il mio con un gradiente e alcune linee diagonali che attraversano:
NOTA: non possiedo il diritto di distribuire standard 07_66, il carattere che sto usando in questo progetto. Scusa per quella cosa.
Tempo di Photoshop: costruiremo la nostra carta con quattro piani (rettangoli piatti) uno di fronte all'altro. Per questo abbiamo bisogno di quattro diversi file di immagine per mappare in quei piani.
I nostri aerei saranno 700x900 e le nostre quattro immagini saranno quindi di quelle dimensioni. La ragione di questa dimensione è dovuta al fatto che gli aerei galleggeranno su uno spazio 3d a una certa distanza dalla telecamera; devono essere grandi in modo che possiamo vederli. Dai un nome alle immagini "page_1_front.jpg", "page_1_back.jpg", "page_2_front.jpg", "page_2_back.jpg" e inseriscile nella cartella radice del tuo progetto.
Ecco le mie immagini:
Queste immagini sono incluse nel codice sorgente principale, ma puoi anche scaricarle direttamente se preferisci ...
Fai lo stesso per un suono se vuoi aggiungerne uno. Scott Wills di audiojungle è stato così gentile da mettere insieme questa traccia funky per noi.
Apri CardViewport.as. Userò FlashDevelop al codice, ma puoi usare Flash se preferisci.
Crea un pacchetto e importa i corsi di cui abbiamo bisogno:
pacchetto // classi di base import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; // classi di papervision import org.papervision3d.objects.primitives.Plane; import org.papervision3d.materials.BitmapFileMaterial; import org.papervision3d.view.BasicView; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.render.QuadrantRenderEngine; // tweening engine import com.greensock.TweenMax;
Imposta le variabili private di cui abbiamo bisogno per CardViewport:
classe pubblica CardViewport estende BasicView // BasicView è una classe che include una configurazione di base per la nostra scena // Crea 4 piani private var front_cover: Plane; private var front_inside: Plane; private var back_cover: Plane; private var back_inside: Plane; // Crea 4 materiali private var front_cover_img: BitmapFileMaterial; private var front_inside_img: BitmapFileMaterial; private var back_cover_img: BitmapFileMaterial; private var back_inside_img: BitmapFileMaterial; // Crea il contenitore della pagina anteriore, che anniderà 2 piani private var front_container: DisplayObject3D; // Crea il contenitore della pagina posteriore, che nidificherà gli altri 2 piani private var back_container: DisplayObject3D; // Crea un contenitore di carte che nidificherà il contenitore frontale e il contenitore posteriore var var card_container: DisplayObject3D;
Ecco la funzione che verrà eseguita quando viene creato CardViewport:
funzione pubblica CardViewport () super (); // per eliminare alcuni errori su come viene calcolata la profondità z nella nostra scena // dobbiamo cambiare il tipo di render in uno che possa correggerlo setRenderType (); // Crea un'istanza dei materiali e imposta le proprietà setMaterials (); // Crea un'istanza degli aerei, aggiunge i materiali ai piani, aggiunge i piani ai wrapper (container) setPlanes (); // rende la camera ogni frame stage.addEventListener (Event.ENTER_FRAME, render); // riposiziona i piani in base alla posizione del mouse stage.addEventListener (MouseEvent.MOUSE_MOVE, positionPlanes);
Per eliminare alcuni errori su come viene calcolata la profondità z nella nostra scena, è necessario modificare il tipo di rendering con uno che può correggere. Il QuadrantRenderEngine accetta un parametro: il tipo di correzione. Questa volta correggeremo il filtro z, usalo saggiamente in quanto può incidere la tua CPU in situazioni complesse.
funzione privata setRenderType () this.renderer = new QuadrantRenderEngine (QuadrantRenderEngine.CORRECT_Z_FILTER)
Anche se non vediamo il quarto piano (il retro della carta) ho deciso di aggiungerlo comunque nel caso volessi giocare con la scena.
Useremo un BitmapFileMaterial, impostando "preciso" su true sto migliorando la qualità generale, però Sto anche usando più potenza della CPU.
funzione privata setMaterials (): void // Front Cover Page front_cover_img = new BitmapFileMaterial ("page_1_front.jpg", true); front_cover_img.doubleSided = false; front_cover_img.fillAlpha = 1.0; // Front Inside Page front_inside_img = new BitmapFileMaterial ("page_1_back.jpg", true); front_inside_img.doubleSided = false; front_inside_img.fillAlpha = 1.0; // Back Inside Page back_inside_img = new BitmapFileMaterial ("page_2_front.jpg", true); back_inside_img.doubleSided = false; back_inside_img.fillAlpha = 1.0; // Back Cover Page back_cover_img = new BitmapFileMaterial ("page_2_back.jpg"); back_cover_img.doubleSided = false; back_cover_img.fillAlpha = 1.0;
Qui creiamo i quattro piani che compongono la nostra carta, disponendoli in un paio di contenitori in modo che appaiano come due pagine.
private function setPlanes (): void // Crea il front Plane Cover front_cover = new Plane (front_cover_img, 700, 900, 3, 3); front_cover.z = 0; front_cover.x = 350 // questo offset verrà usato in seguito in modo che possiamo aprire la carta // Crea l'interno del piano frontale front_inside = new Plane (front_inside_img, 700, 900, 3, 3); front_inside.z = 0; front_inside.rotationY = 180; // ruotato di 180 gradi in modo che possiamo vederlo dall'interno front_inside.x = 350 // è esattamente la metà della larghezza del piano // Crea un oggetto wrapper in modo che possiamo ruotare la pagina anteriore da un altro asse // quello delle pagine. È più semplice in questo modo in quanto non devi incasinare con le coordinate della creazione // e possiamo semplicemente controbilanciarlo. front_container = new DisplayObject3D (); front_container.addChild (front_cover); front_container.addChild (front_inside); front_container.x- = 350 // qui lo stiamo sfalsando // Ripeti il processo per la seconda pagina back_inside = new Plane (back_inside_img, 700, 900, 3, 3); back_inside.z = 0,1; back_inside.x = 350 back_cover = new Plane (back_cover_img, 700, 900, 3, 3); back_cover.z = 0,1; back_cover.rotationY = 180; back_cover.x = 350 back_container = new DisplayObject3D (); back_container.addChild (back_inside); back_container.addChild (back_cover); back_container.x - = 350 // E dopo tutto aggiungi i contenitori anteriore e posteriore al wrapper principale e aggiungi il wrapper alla scena. card_container = new DisplayObject3D (); card_container.addChild (front_container) card_container.addChild (back_container) scene.addChild (card_container);
Si noti che questa è una funzione pubblica, quindi è possibile accedervi tramite la classe del documento principale quando si fa clic sul pulsante:
public function openCard () // Quando apriamo la scheda dobbiamo rimuovere gli ascoltatori del mouse dallo stage perché // quando muoviamo il mouse ruotiamo roba, a volte i contenitori a volte gli stessi piani, // quindi non possiamo ruotare entrambi contemporaneamente come ci ritroveremo con errori di animazione stage.removeEventListener (MouseEvent.MOUSE_MOVE, positionPlanes); // abbiamo bisogno di ripristinare le posizioni dei piani all'interno dei container resetPlanesPosition (); // ruotiamo il contenitore anteriore di 180 gradi e impostiamo la x su 0, // perché spostiamo i piani prima che ora ruotino di conseguenza. TweenMax.to (front_container, 1.4, rotationY: 180, x: 0, onComplete: function () stage.addEventListener (MouseEvent.MOUSE_MOVE, positionContainer);); TweenMax.to (back_container, 1.4, x: 0); // dopo la rotazione aggiungiamo un nuovo listener al mouse. questa volta per riposizionare il contenitore principale.
Lo stesso per la chiusura della carta:
public function closeCard () // quando chiudiamo la carta i passaggi sono molto simili a quando apriamo. stage.removeEventListener (MouseEvent.MOUSE_MOVE, positionContainer); // differenza è dove ripristiniamo la rotazione del contenitore principale card_container.rotationY = card_container.rotationX = 0 // azzeriamo i container anteriori e posteriori 'xe proprietà rotationY TweenMax.to (front_container, 1.4, rotationY: 0, x: - 350, onComplete: function () stage.addEventListener (MouseEvent.MOUSE_MOVE, positionPlanes);); TweenMax.to (back_container, 1.4, x: -350); // e dopo l'animazione aggiungiamo l'azione evento precedente del mouse move per posizionare i piani
Questo viene chiamato ogni volta che il mouse viene spostato mentre la carta è chiusa:
posizione di funzione privataPrima (evento: Evento): void // ruota tra -25º e 25º a seconda della posizione del mouse front_cover.rotationY = back_inside.rotationY = (stage.mouseX / stage.stageWidth * 50) -25 front_cover.rotationX = front_inside.rotationX = back_cover.rotationX = back_inside.rotationX = (stage.mouseY / stage.stageHeight * 50) - 25 // abbiamo solo bisogno di aggiungere 180 ai volti che dovrebbero essere contro di noi front_inside.rotationY = back_cover.rotationY = ((stage.mouseX / stage.stageWidth * 50) - 25) + 180
Questo viene chiamato ogni volta che il mouse viene spostato mentre la carta è aperta:
funzione privata positionContainer (event: Event): void // proprio come gli aerei. ruota tra -25º e 25º a seconda della posizione del mouse card_container.rotationY = (stage.mouseX / stage.stageWidth * 50) -25 card_container.rotationX = (stage.mouseY / stage.stageHeight * 50) - 25
Questo viene chiamato quando si fa clic sulla carta per aprire:
funzione privata resetPlanesPosition () // il nome della funzione sais tutto, ruota gli aerei nella posizione originale creata front_inside.rotationY = back_cover.rotationY = 180 front_cover.rotationY = back_inside.rotationY = front_cover.rotationX = front_inside.rotationX = back_cover.rotationX = back_inside.rotationX = 0
L'ultimo passaggio è ovviamente il rendering della vista, dopodiché passiamo alla classe del documento.
private function render (event: Event): void // singleRender è una funzione di BasicView che attiva il rendering in quel dato momento. singleRender ();
Questa è la fine della lezione. Non dimenticare di aggiungere le parentesi graffe di chiusura.
Non cambieremo nient'altro nella classe CardViewport, quindi sentiti libero di ottenere la fonte dal file zip e confrontarla con la tua.
Questo passaggio è abbastanza semplice, abbiamo solo bisogno di associare la scheda aperta e chiudere le azioni della carta al pulsante. Prima di ciò, importiamo le seguenti classi nel nostro pacchetto:
package import flash.display.MovieClip; import flash.events.Event; import flash.events.MouseEvent; import flash.media.Sound; // ricorda il compleanno.mp3? sarà aggiunto qui import flash.net.URLRequest;
Ancora una volta, niente di eccezionale, estende MovieClip e crea un oggetto Sound:
public class Main estende MovieClip private var birthday_song: Sound
Ecco un piccolo consiglio per voi: per evitare errori nulli, inizializzate i vostri comandi solo dopo che la classe è stata aggiunta allo stage. In questo modo sei sicuro che tutto ciò che stai cercando di accedere è presente.
funzione pubblica Main (): void addEventListener (Event.ADDED_TO_STAGE, init)
... e questa è la funzione che verrà eseguita quando la classe del documento è stata aggiunta allo stage:
funzione privata init (event: Event): void removeEventListener (Event.ADDED_TO_STAGE, init) // non abbiamo più bisogno di questo open_mc.label_txt.text = "_! OPEN CARD! _" // Etichette il pulsante open_mc.buttonMode = vero; // Imposta il pulsante per agire come un pulsante open_mc.mouseChildren = false; // Disabilita gli eventi del mouse su open_mc child open_mc.addEventListener (MouseEvent.CLICK, openCard) // Aggiunge un listener di eventi al clic del mouse
Questa funzione verrà eseguita quando si fa clic sulla scheda se è chiusa:
funzione privata openCard (event: MouseEvent): void open_mc.removeEventListener (MouseEvent.CLICK, openCard); // rimuove il listener aperto viewport.openCard (); // accedi al viewport per aprire la scheda (ricorda che l'abbiamo resa pubblica in precedenza?) open_mc.label_txt.text = "_! CLOSE CARD! _" // cambia l'etichetta open_mc.addEventListener (MouseEvent.CLICK, closeCard) // aggiunge un ascoltatore per chiudere la scheda al clic del mouse birthday_song = new Sound (new URLRequest ("birthday.mp3")); // carica la canzone di compleanno birthday_song.play (); // riproduce la canzone del compleanno
Questo è praticamente lo stesso di OpenCard (), ma al contrario. ;)
private function closeCard (event: MouseEvent): void open_mc.removeEventListener (MouseEvent.CLICK, closeCard) viewport.closeCard (); open_mc.label_txt.text = "_! OPEN CARD! _" open_mc.addEventListener (MouseEvent.CLICK, openCard)
Finito. Nessun segreto in questa classe di documenti, è abbastanza semplice. Non dimenticare di aggiungere le parentesi graffe di chiusura.
Mi piacerebbe vederti evolvere da questo tutorial riprendendo alcuni dei piccoli consigli che ti ho dato, dal ADDED_TO_STAGE al wrapper displayObject3d, all'utilizzo di una classe di tweening per ruotare e spostare un oggetto 3d. Prendi questa carta e falla tua.
Buon compleanno Activetuts +! Spero che questo tutorial ti sia piaciuto, grazie per la lettura!