În tutorialul meu precedent Shoot Out Stars cu motorul Stardust Particle, am explicat fluxul de lucru de bază al Stardust. De data aceasta, vom lua lucrurile mai departe și vom examina câteva tehnici pentru a crea efectele 3D ale particulelor!
Vom începe cu o demonstrație a utilizării motorului nativ 3D Stardust. Apoi, vă voi arăta cum să obțineți Stardust să lucreze cu Papervision3D; vom crea efecte 3D ale particulelor cu clasa Particulele lui Papervision3D și clasa DisplayObject3D.
Vom ridica locul unde am rămas în primul tutorial. Ultima dată când am creat particule de tip stea și cerc care trag dintr-un punct, crescând la o dimensiune maximă și apoi scăzând la nimic, în timp ce se mișcă treptat mai lent în timp (numit efect de amortizare). De data aceasta, vom face același lucru, dar în 3D. În locul particulelor care se deplasează într-un cerc, se vor muta într-o sferă.
La fel ca înainte, creați mai întâi un nou document Flash cu dimensiunile de 640x400, o rată a cadrelor de 60fps și un fond întunecat (am folosit un gradient albastru închis).
Desenați o stea și un cerc alb, apoi convertiți-le în simboluri, separat. Acestea sunt cele două simboluri pe care le vom folosi ca particule mai târziu. Denumiți simbolul stea "Stelu" și simbolul cercului "Cerc", exportat pentru ActionScript cu aceleași nume de clase.
(Dacă nu sunteți prea mult artist, puteți descărca sursa din partea de sus a paginii și utilizați simbolurile mele din biblioteca FLA.)
Clic Fereastră> Componente pentru a afișa panoul Componente, apoi glisați un buton din dosarul Interfață utilizator pe scenă. Setați eticheta la "Pauză" și denumiți-o "pause_btn". Vom folosi acest buton pentru a întrerupe efectele particulelor 3D, permițând astfel utilizatorilor să învârte aparatul în jurul său pentru a obține un gust mai bun al mediului 3D.
Creați o nouă clasă de documente și denumiți-o StarParticles3D.
pachet import flash.display.Sprite; clasa publică StarParticles3D extinde Sprite funcția publică StarParticles ()
Nu sunteți sigur cum să utilizați o clasă de documente? Citiți acest sfat rapid.
Cele trei pachete principale din Stardust sunt:
În tutorialul precedent am folosit inițiale și acțiuni din pachetele comune și 2D. În acest tutorial, vom folosi în continuare elemente din pachetul comun, dar nu din pachetul twoD. În schimb, vom folosi elemente din pachetul trei.
Structura clasei pachetului threeD este aproape la fel ca în pachetul twoD, cu excepția faptului că elementele au o dimensiune suplimentară. Un element 3D are același nume ca omologul său 2D, dar numele său se termină cu "3D". De exemplu, Move3D acțiunea în pachetul 3D actualizează pozițiile particulelor în spațiul 3D în funcție de viteze, la fel ca și 2D-ul său în pachetul 2D, Mișcare acțiune.
Creați un nou fișier AS numit StarEmitter.as; în interiorul său, creați o nouă clasă StarEmitter, care extinde clasa Emitter3D:
pachet import idv.cjcat.stardust.threeD.emitters.Emitter3D; // nu uitați să importați acest lucru! clasa publică StarEmitter extinde Emitter3D funcția publică StarEmitter (ceas: ceas) // trece obiectul ceasului la constructorul superclass super (ceas);
Amintiți-vă parametrul Ceas? Este folosit pentru a controla rata de formare a particulelor. Trebuie să-l includem în funcția de constructor, astfel încât să putem transmite un Ceas mai târziu.
Deoarece permitem utilizatorilor să întrerupă efectele particulelor, vom împacheta toate acțiunile într-un singur obiect CompositeAction, care este în esență un grup de acțiuni. Prin dezactivarea acestei singure acțiuni compuse, putem "dezactiva" toate acțiunile subiacente. Declarați o variabilă pentru o acțiune compusă în clasa emițătorului. Vom accesa această variabilă în clasa de documente, deci trebuie să fie publică:
public var pausibleActions: CompositeAction;
Declarați constantele care vor fi folosite ca parametri de particule în clasa emițătorului. Am acoperit deja scopul acestor constante în tutorialul anterior. Majoritatea denumirilor sunt explicite. Acestea intră în clasă, dar în afara funcției constructorului. Simțiți-vă liber să reveniți aici mai târziu și să modificați numerele pentru a vedea efectele.
contabil static privat LIFE_AVG: Number = 30; contabil static privat LIFE_VAR: Number = 10; static static const SCALE_AVG: Number = 1; static static const SCALE_VAR: Number = 0.4; constr. statică privată GROWING_TIME: Număr = 5; constrângere statică privată SHRINKING_TIME: număr = 10; constrângere statică privată SPEED_AVG: Number = 30; static static const SPEED_VAR: Number = 10; constrângere statică privată OMEGA_AVG: Number = 0; static static const OMEGA_VAR: Number = 5; constanta statică privată DAMPING: Number = 0.1;
În tutorialul precedent am demonstrat cum să folosiți SwitchInitializer pentru a crea particule cu diferite obiecte de afișare. Am folosit inițializatorul DisplayObjectClass, care inițializează aspectul particulelor cu obiecte de afișare. Asta a fost pentru efectele particulelor 2D; aici vom folosi omologul său 3D, inițializatorul DisplayObject3D.
Adăugați următorul cod la funcția constructorului emitorului:
// initializatori comutator pentru particule de stea și cerc var doc1: DisplayObjectClass3D = new DisplayObjectClass3D (Star); var doc2: DisplayObjectClass3D = nou DisplayObjectClass3D (Cerc); var si: SwitchInitializer = noul SwitchInitializer ([doc1, doc2], [1, 1]); addInitializer (si);
La fel ca tutorialul anterior; adăugați celelalte inițializatoare prezentate mai jos. Rețineți că unele dintre ele au nume similare celor din tutorialul anterior, însă se termină cu "3D".
Acest cod merge în funcția constructorului StarEmitter:
addInitializer (noua viață (noul UniformRandom (LIFE_AVG, LIFE_VAR))); addInitializer (noua scară (noul UniformRandom (SCALE_AVG, SCALE_VAR))); addInitializer (new Position3D (new SinglePoint3D ())); addInitializer (noul Velocity3D (noul SphereShell (0, 0, 0, SPEED_AVG, SPEED_VAR))); addInitializer (noua rotație3D (null, null, new UniformRandom (0, 180))); addInitializer (nou Omega3D (null, null, new UniformRandom (OMEGA_AVG, OMEGA_VAR)));
Creați o acțiune compusă și adăugați anumite acțiuni. Apoi, adăugați această acțiune compusă la emițător; acest lucru va face ca particulele să efectueze acțiunile. Ați văzut aceste acțiuni în tutorialul anterior (unele dintre ele în versiunea 2D), așa că nu le voi explica din nou. Din nou, acest cod merge în funcția constructorului StarEmitter:
pausibleActions = nou CompositeAction (); pausibleActions.addAction (new Age ()); pausibleActions.addAction (noul DeathLife ()); pausibleActions.addAction (noul Move3D ()); pausibleActions.addAction (nou Spin3D ()); pausibleActions.addAction (noua amortizare3D (DAMPING)); pausibleActions.addAction (noul ScaleCurve (GROWING_TIME, SHRINKING_TIME)); addAction (pausibleActions);
În regulă, am terminat cu emițătorul. Acum este momentul să construim clasa noastră de documente.
Mai întâi, declarați constantele pentru raza orbitei camerei, distanța dintre camera și origine și rata emițătorului:
statică statică privată CAMERA_RADIUS: Number = 250; static static const PARTICLE_RATE: Number = 0.5;
(Ca și înainte, conists intra în clasă, dar în afara funcției constructorului.)
Apoi, declarați variabile pentru un emițător, un ceas constant și un DisplayObjectRenderer3D (în același loc ca și consts):
emițător privat var: StarEmitter; privat ceas var: SteadyClock; privat var renderer: DisplayObjectRenderer3D;
În constructor, inițializați ceasul, emițătorul și redarea. De asemenea, setați poziția și direcția camerei inițiale, făcându-o să privească originea:
// crea ceasul și emițătorul = noul SteadyClock (PARTICLE_RATE); emitator = StarEmitter nou (ceas); // putem face acest lucru pentru că am dat constructorului lui StarEmitter un parametru de ceas / / crează renderer și containerul lui sprite var container: Sprite = new Sprite (); container.x = 320, container.y = 200; renderer = nou DisplayObjectRenderer3D (container); renderer.addEmitter (emițător); // adăugați containerul în etapa addChild (container); // adăugați din nou butonul de pauză, astfel încât să se afle pe partea de sus a containerului addChild (pause_btn); // setați poziția inițială a camerei și direcția renderer.camera.position.set (0, 0, -CAMERA_RADIUS); renderer.camera.direction.set (0, 0, CAMERA_RADIUS);
Creați o funcție de manipulare în clasa de documente pentru a gestiona evenimentul clic al butonului de pauză:
funcția privată togglePause (e: MouseEvent): void if (e.target.label == "Pauză") e.target.label = "Reluați"; clock.ticksPerCall = 0; // opriți ceasul emitter.pausibleActions.active = false; // dezactivați acțiunile emițătorului altceva e.target.label = "Pauză"; clock.ticksPerCall = PARTICLE_RATE; // reporniți ceasul emitter.pausibleActions.active = true; // reactivarea acțiunilor emitentului
... apoi înregistrați ascultătorul pentru butonul de pauză, în funcția constructor:
pause_btn.addEventListener (MouseEvent.CLICK, togglePause);
Creați un handler pentru evenimentul ENTER_FRAME. Aceasta este bucla noastră principală. Acesta actualizează poziția camerei apelând metoda updateCamera () (pe care o vom codifica într-un minut) și sună metoda step () a emițătorului, care menține efectele particulelor care rulează:
funcția privată mainLoop (e: Eveniment): void updateCamera (); emitter.step ();
Din nou, înregistrați un ascultător în constructor:
addEventListener (Event.ENTER_FRAME, mainLoop);
Acum definiți metoda updateCamera () numită în pasul anterior. Aceasta este folosită pentru a deplasa camera în spațiul 3D, în funcție de poziția mouse-ului. (Dacă doriți mai multe informații despre cum funcționează, verificați acest articol Wikipedia.)
Numerele magice folosite pentru a genera theta și phi sunt doar rezultatul încercărilor și erorilor; nu ezitați să încercați propriile dvs. ecuații.
funcția privată updateCamera (): void var theta: Number = 0.02 * (mouseX-320); var phi: Număr = 0,02 * (șoarece Y-200); phi = StardustMath.clamp (phi, -StardustMath.HALF_PI, StardustMath.HALF_PI); var x: Număr = CAMERA_RADIUS * Math.cos (theta) * Math.cos (phi); var y: Numărul = CAMERA_RADIUS * Math.sin (phi); var z: Număr = CAMERA_RADIUS * Math.sin (theta) * Math.cos (phi); ranerer.camera.position.set (x, y, z); renderer.camera.direction.set (-x, -y, -z);
Rețineți că am folosit metoda StardustMath.clamp (); acest lucru face ca valoarea phi sa fie mentinuta intre jumatate PI pozitiv si negativ.
Bine, am terminat! Asta e tot ce trebuie să facem pentru a obține un emițător 3D care să funcționeze cu motorul nativ 3D Stardust. Să vedem rezultatul. Puteți să faceți clic pe butonul de pauză pentru a întrerupe efectul de particule și pentru a deplasa mouse-ul în jurul orbitei camerei:
Demo Vizualizați-l onlineDacă doriți să vedeți codul sursă complet, căutați în directorul "01 - Stardust Native 3D Engine" în Sursă.
Trecerea de la motorul 3D nativ al Stardust la Papervision3D este ușor. Va trebui doar să folosim un alt renderer și să afișăm inițializatorul de obiecte.
(Nu a mai fost folosit vreodată Papervision3D? Uitați-vă la tutorialul acestui începător.)
Mai întâi vom folosi clasa Particulelor lui Papervision3D. S-ar putea să nu fiți familiarizați cu acest lucru; Vă voi arăta cum să utilizați mai târziu clasa DisplayObject3D.
Modificați următorul cod în clasa emițătorului:
var doc1: DisplayObjectClass3D = noul DisplayObjectClass3D (Star); var doc2: DisplayObjectClass3D = nou DisplayObjectClass3D (Cerc);
la acest:
var mat1: MovieParticleMaterial = MovieParticleMaterial nou (Star nou ()); var mat2: MovieParticleMaterial = filmul MovieParticleMaterial (noul Cerc ()); var doc1: PV3DParticle = nou PV3Particule ([mat1]); var doc2: PV3DParticle = noua piesă PV3DP ([mat2]);
După cum probabil știți deja, clasa MovieParticleMaterial ne permite să folosim obiecte de afișare ca aspect de particule în Papervision3D. Creăm un exemplu Star și Circle pentru a fi folosit ca material de particule. Initializatorul PV3DParticle înlocuiește inițializatorul DisplayObjectClass3D; constructorul său acceptă o serie de parametri, care vor fi adăugați la un obiect Particule.
Acesta este tot ce trebuie să facem în legătură cu emițătorul. Apoi vom modifica clasa de documente.
Containerul țintă pentru redactorul nostru nu mai este un obiect Sprite. În schimb, vom crea particule într-un obiect Particule. Va trebui să schimbăm tipul de redare de la DisplayObjectRenderer3D la PV3DParticleRenderer.
Declarați următoarele variabile pentru obiectele legate de Papervision3D:
privat var scenă: SceneObject3D; particule particulare var: particule; camera privată var: Camera3D; privat var var: DisplayObject3D; private var renderEngine: BasicRenderEngine; privat fereastră de vizualizare: Viewport3D;
Codul din constructorul clasei de documente este acum:
initPV3D (); //Acesta este nou! ceas = nou SteadyClock (PARTICLE_RATE); emitator = StarEmitter nou (ceas); renderer = nou PV3DParticleRenderer (particule); //Acesta este nou! renderer.addEmitter (emițător); pause_btn.addEventListener (MouseEvent.CLICK, togglePause); addEventListener (Event.ENTER_FRAME, mainLoop);
Metoda initPV3D () stabilește mediul Papervision3D. Iată codul:
funcția privată initPV3D (): void // crea scena scene = nou SceneObject3D (); // a crea particule particulare de particule = particule noi (); // creați camera și inițiați camera foto = noua cameră 3D (); camera.position.x = 0; camera.position.y = 0; camera.position.z = -CAMERA_RADIUS; // creați un DO3D reprezentând originea originării = new DisplayObject3D (); origin.x = origin.y = origin.z = 0; // îndreptați aparatul foto la originea camerei.target = origine; scene.addChild (origine); scene.addChild (particule); // creați motorul de redare și fereastra de vizualizare renderEngine = new BasicRenderEngine (); viewport = noul Viewport3D (640, 400); // adăugați fereastra de vizualizare la scena addChild (viewport); // adăugați din nou butonul de pauză, astfel încât să se afle deasupra ferestrei de vizualizare addChild (pause_btn);
Acum, Stardust actualizează numai proprietățile obiectelor 3D; Motorul de randare al lui Papervision3D își asumă responsabilitatea de redare. Aceasta este ceea ce arată noua noastră bucla principală:
funcția privată mainLoop (e: Eveniment): void updateCamera (); emitter.step (); renderEngine.renderScene (scena, camera, vizualizare); //Acesta este nou!
Acum, când folosim camera lui Papervision3D, va trebui să modificăm și metoda updateCamera ():
funcția privată updateCamera (): void var theta: Number = 0.02 * (mouseX-320); var phi: Număr = 0,02 * (șoarece Y-200); phi = StardustMath.clamp (phi, -StardustMath.HALF_PI, StardustMath.HALF_PI); var x: Număr = CAMERA_RADIUS * Math.cos (theta) * Math.cos (phi); var y: Numărul = -CAMERA_RADIUS * Math.sin (phi); // nota este negativ acum var z: Number = CAMERA_RADIUS * Math.sin (theta) * Math.cos (phi); camera.x = x; // actualizăm fiecare dintre proprietățile x, y, z aparatului foto PV3D separat camera.y = y; camera.z = z;
Bine, am trecut cu succes de la motorul 3D nativ al lui Stardust la Papervision3D. Acum să verificăm rezultatul. Rețineți efectul de pixelizare asupra particulelor. Acest lucru se datorează faptului că Papervision3D desenează mai întâi obiecte vectoriale în bitmap-uri înainte de a le folosi ca materiale de particule.
Demo Vizualizați-l onlinePuteți găsi toate codurile sursă pentru acest lucru în folderul "02 - Papervision3D Particles".
Până acum, lucrăm cu "panouri 2D" - obiecte plate, cum ar fi hârtia. Este posibil să se creeze obiecte de particule 3D "reale", cum ar fi obiectele DisplayObject3D ale lui Papervision3D. Trebuie să folosim un alt inițializator. Acum, să ajungem la partea finală a acestui tutorial. Vom crea particule de cub rosu si albastru.
Vom schimba inițializatorul pentru aspectul particulelor pentru ultima oară.
Înainte de aceasta, declarați o variabilă LightObject3D în clasa emițătorului. Vom folosi materialul FlatShadeMaterial pentru obiectele DisplayObject3D, care necesită o sursă de lumină. De asemenea, declarați următoarele constante - le vom folosi ca parametri pentru FlastShadeMaterial și pentru determinarea dimensiunilor cuburilor:
public var lumina: LightObject3D; constr. statică privată LIGHT_COLOR_1: uint = 0xCC3300; constr. statică privată LIGHT_COLOR_2: uint = 0x006699; constr. statică privată AMBIENT_COLOR_1: uint = 0x881100; static static const AMBIENT_COLOR_2: uint = 0x002244; statică statică privată CUBE_SIZE: Number = 15;
Acum schimbați următorul cod în clasa emițătorului:
var mat1: MovieParticleMaterial = MovieParticleMaterial nou (Star nou ()); var mat2: MovieParticleMaterial = filmul MovieParticleMaterial (noul Cerc ()); var doc1: PV3DParticle = nou PV3Particule ([mat1]); var doc2: PV3DParticle = noua piesă PV3DP ([mat2]);
la acest:
light = nou LightObject3D (); var mat1: FlatShadeMaterial = FlatShadeMaterial nou (lumină, LIGHT_COLOR_1, AMBIENT_COLOR_1); var mat2: FlatShadeMaterial = nou material FlatShadeMaterial (lumină, LIGHT_COLOR_2, AMBIENT_COLOR_2); var matList1: MaterialsList = MaterialeList noi (toate: mat1); var matList2: MaterialsList = materiale noi (toate: mat2); var params1: Array = [matList1, CUBE_SIZE, CUBE_SIZE, CUBE_SIZE]; var params2: Array = [matList2, CUBE_SIZE, CUBE_SIZE, CUBE_SIZE]; var doc1: PV3DDisplayObject3DClass = nou PV3DDisplayObject3DClass (Cube, params1); var doc2: PV3DDisplayObject3DClass = nou PV3DDisplayObject3DClass (Cube, params2);
Apariția noului particulă va fi inițializată ca cuburi 3D roșii și albastre. Primul parametru constructor pentru inițiatorul PV3DDisplayObject3DClass este clasa pe care dorim să o instanțiăm pentru particule (deci aici este clasa Cube) iar al doilea parametru este o serie de parametri constructori pentru această clasă Cube.
Anterior, pentru că lucrăm cu "panouri 2D", numai rotația axei Z a avut importanță. Acum, când lucrăm cu obiecte 3D adevărate, trebuie să trecem trei referințe de obiect Randal la constructorii Rotation3D și Omega3D, câte unul pentru fiecare axă.
Modificați următorul cod în clasa emițătorului:
addInitializer (noua rotație3D (null, null, new UniformRandom (0, 180))); addInitializer (nou Omega3D (null, null, new UniformRandom (OMEGA_AVG, OMEGA_VAR)));
la acest:
Var rotationRandom: UniformRandom = nou UniformRandom (0, 180); var omegaRandom: UniformRandom = nou UniformRandom (OMEGA_AVG, OMEGA_VAR); addInitializer (noul Rotation3D (rotationRandom, rotationRandom, rotationRandom)); addInitializer (noul Omega3D (omegaRandom, omegaRandom, omegaRandom));
De data aceasta, în loc să folosim un obiect Particule ca container de particule, folosim ca container un DisplayObject3D. Declarați o variabilă pentru acest container în clasa de documente:
container privat var: DisplayObject3D;
De asemenea, vom avea nevoie de un alt tip de redare pentru a crea particule în noul container. Modificați tipul de redare de la PV3DParticleRenderer la PV3DDisplayObject3DRenderer. Codul din constructorul clasei document ar trebui să arate astfel:
initPV3D (); ceas = nou SteadyClock (PARTICLE_RATE); emitator = StarEmitter nou (ceas); renderer = nou PV3DDisplayObject3DRenderer (container); // aceasta sa schimbat! renderer.addEmitter (emițător); pause_btn.addEventListener (MouseEvent.CLICK, togglePause); addEventListener (Event.ENTER_FRAME, mainLoop);
În funcția initPV3D (), trebuie să inițializăm variabila containerului și să o adăugăm la scenă. Adăugați aceste două linii la sfârșitul acestei funcții:
container = nou DisplayObject3D (); scene.addChild (container);
În metoda updateCamera (), dorim să facem ca lumina să urmărească camera, așa că vom avea o iluzie că lumina mereu "iese" din ochii noștri. Modificați următorul cod:
camera.x = x; camera.y = y; camera.z = z;
la acest:
emitter.light.x = camera.x = x; emitter.light.y = camera.y = y; emitter.light.z = camera.z = z;
Acum, sursa de lumină este mereu în același punct cu camera.
Da, am terminat în sfârșit cu acest tutorial. Nu mai există codificare. Să aruncăm o privire asupra rezultatului nostru final, cu cuburi 3D roșii și albastre!
Demo Vizualizați-l onlineCodul sursă pentru acest lucru poate fi găsit în folderul "Papervision3D DisplayObject3D".
Fluxul de lucru pentru crearea efectelor 3D ale particulelor cu Stardust este aproape la fel ca în cazul efectelor 2D. Alegeți doar un set diferit de inițiale, acțiuni și redare. Stardust suportă și alte motoare 3D, inclusiv ZedBox și ND3D. Utilizarea este aproape la fel. Veți fi nevoit să utilizați un set diferit de inițiale și redare. Puteți chiar să extindeți clasele Initializer, Action și Renderer pentru a lucra cu oricare dintre motoarele 3D care vă plac!
Acum, aveți elementele de bază, de ce nu vă întoarceți la constrele create la pasul 6 și jucați cu ele pentru a vedea efectele?
Sper că acest tutorial vă ajută să înțelegeți mai mult Stardust și vă face mai familiar și mai confortabil cu fluxul de lucru al Stardust. Vă mulțumim pentru lectură!