Create 3D effekter med Stardust Particle Engine 
 Del 
 Del 
 to 
 Del 
 Dette Cyber Monday Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av. 
 
 I min forrige tutorial Shoot Out Stars med Stardust Particle Engine, forklarte jeg den grunnleggende arbeidsflyten av Stardust. Denne gangen vil vi ta ting videre og undersøke et par teknikker for å skape ekte 3D partikkel effekter! 
 
 
 
Innledning
 Vi begynner med en demonstrasjon av hvordan du bruker Stardust native 3D-motor. Deretter vil jeg vise deg hvordan du får Stardust å jobbe med Papervision3D; vi skal opprette 3D partikkel effekter med Papervision3D sin Partikler klasse og DisplayObject3D klasse. 
 
Tidligere ...
 Vi kommer til å fortsette der vi slapp i første opplæringen. Sist gang vi skapt stjerne og sirkel partikler skyte ut fra et punkt, vokser til en maksimal størrelse og deretter krymper til ingenting, mens de beveger seg gradvis tregere over tid (kalt en dempende effekt). Denne gangen vil vi gjøre det samme, men i 3D. I stedet for partiklene beveger seg i en sirkel, vil de flytte ut i en sfære 
 
Trinn 1:. Opprette en ny Flash dokument
 På samme måte som før, først opprette en ny Flash dokument med dimensjoner på 640x400, en bildefrekvens på 60 bilder per sekund, og en mørk bakgrunn (jeg brukte en mørk blå gradient) 
 
Trinn 2:. Tegn Partikler
 Tegn en stjerne og en hvit sirkel, deretter konvertere dem til symboler, separat. Dette er de to symbolene vi skal bruke som partikler senere. Navn stjernen symbolet "Star" og sirkel symbol "Circle", eksporteres for Action med de samme klassenavn. 
 
 (Hvis du ikke er mye av en artist, kan du laste ned kilde på toppen av side og bruke mine symboler fra biblioteket mitt FLA) 
 
Trinn 3: Opprett pauseknapp
 Klikk på  Vindu >. Komponenter   Opprett et nytt dokument klasse og name it StarParticles3D   Ikke sikker på hvordan du bruker et dokument klasse? Les denne Quick Tips   De tre viktigste pakker i Stardust er:.   I forrige tutorial brukte vi initializers og handlinger fra de vanlige og twoD pakker. I denne opplæringen, vil vi fortsatt være å bruke elementer fra den vanlige pakken, men ikke fra twoD pakken. I stedet vil vi benytte elementer fra threeD pakken.   klassestrukturen i threeD pakken er stort sett den samme som i den twoD pakken, med unntak av at elementene har en ekstra dimensjon. En 3D-element besitter samme navn som sin 2D motstykke, men navnet slutter med "3D". For eksempel  Move3D   Opprett en ny AS fil som heter  StarEmitter.as   Husk klokken parameter? Den brukes til å styre frekvensen av partikkel skapelsen. Vi trenger å ta det med i konstruktør-funksjon, slik at vi kan passere en klokke til det senere.   Siden vi tillater brukere å pause partikkel effekter, kommer vi til å pakke alle handlingene til én CompositeAction objekt, som er egentlig en gruppe av handlinger. Ved å deaktivere dette enkelt sammensatt handling, kan vi "slå av" alle de underliggende handlinger. Deklarere en variabel for en sammensatt handling i emitter klassen. Vi vil få tilgang til denne variabelen i dokumentet klassen, så det må være offentlig:   Erklærer konstanter som vil brukes som partikkel parametre i emitter-klassen. Vi har allerede dekket hensikten med disse konstanter i forrige tutorial. De fleste av navnene er selvforklarende. Disse går inn i klassen, men utenfor konstruktøren funksjon. . Føl deg fri til å komme tilbake hit senere og endre tallene for å se effektene   I forrige tutorial jeg demonstrert hvordan du bruker SwitchInitializer å skape partikler med ulike visningsobjekter. Jeg var bruker DisplayObjectClass initializer, som initialiserer partikkel utseende med visningsobjekter. Det var for 2D-partikkel effekter; her vi kommer til å bruke sin 3D motstykke, den DisplayObject3D initializer   Legg til følgende kode i emitter konstruktør funksjon.   Samme som forrige tutorial; legge de andre initializers vist nedenfor. Vær oppmerksom på at noen av dem har lignende navn til de i forrige tutorial, men ender i "3D".   Denne koden går i StarEmitter konstruktør funksjon.   Lag en sammensatt handling, og legge til noen handlinger til det. Deretter legger denne sammensatte tiltak for å emitter; dette vil gjøre partiklene utføre handlingene. Du har sett disse handlingene i forrige tutorial (noen av dem i 2D-versjon), så jeg vil ikke forklare dem på nytt. Igjen, går denne koden i StarEmitter konstruktør funksjon:   Greit, vi er ferdige med emitter. Nå er det på tide å bygge vårt dokument klasse   Først erklærer konstanter for bane kameraets radius, kameraet avstanden fra origo og emitter rate:   (Som før consts gå inn i klassen, men utenfor konstruksjonsfunksjonen.)   Deretter deklarere variabler for en emitter, en stabil klokke og en DisplayObjectRenderer3D (i samme sted som consts):   I konstruktøren, initialisere klokke, emitter og renderer. Sett også innledende kameraets posisjon og retning, slik at det ser på opprinnelsen:   Opprett en handler funksjon i dokumentet klassen til å håndtere et klikk tilfelle på pauseknappen:   .. deretter registrere lytteren for pauseknappen, i konstruktør-funksjon:   Opprett et behandlingsprogram for ENTER_FRAME hendelsen. Dette er vårt viktigste loop. Den oppdaterer kameraets posisjon ved å ringe updateCamera () metode (som vi vil kode i et minutt) og kaller emitter er trinn () -metoden, som holder partikkel effekter kjører:   Igjen, registrere en lytter i konstruktøren:   Nå definerer updateCamera () metode som kalles i forrige trinn. Dette brukes for å flytte kameraet i 3D-rom avhengig av musens posisjon. (Hvis du ønsker mer informasjon om hvordan det fungerer sjekk ut denne Wikipedia-artikkelen.)   Den magiske tall som brukes til å generere theta og phi er bare et resultat av prøving og feiling; gjerne prøve dine egne ligninger   Legg merke til at jeg brukte StardustMath.clamp () metoden; dette gjør at phi verdien holdes mellom positive og negative halv PI   Ok, vi er ferdig! Det er alt vi trenger å gjøre for å få en 3D-emitter jobbe med Stardust har native 3D-motor. La oss se på resultatet. Du kan klikke på pauseknappen for å stanse partikkel effekt, og flytte musen rundt i bane kameraet:   Hvis du ønsker å se hele kildekoden, se i mappen som heter " 01 -. Stardust Native 3D Engine "i kilde   Hvis du vil bytte fra Stardust innfødt 3D-motor til Papervision3D er enkelt. Vi må bare bruke en annen renderer og vise objekt initializer.   (Aldri brukt Papervision3D før? Ta en titt på denne nybegynner opplæringen.)   Først vil vi bruke Papervision3D sin Partikler klasse . Du er kanskje ikke kjent med dette; Jeg skal vise deg hvordan du bruker den mer vanlige DisplayObject3D klassen senere   Endre følgende kode i emitter klassen:   til dette:   Som du kanskje allerede vet, gjør at MovieParticleMaterial klassen oss til bruke visningsobjekter som partikler 'opptreden i Papervision3D. Vi skaper en stjerne og Circle eksempel skal brukes som partikkelmateriale. Den PV3DParticle initializer tar plassen til den DisplayObjectClass3D initializer; sin konstruktør godtar en rekke parametre, som alle vil bli lagt til en Particles objekt.   Dette er alt vi har å gjøre med hensyn til emitter. Neste vi vil endre dokumentet klassen   Målet beholder for vår renderer er ikke lenger en Sprite objekt. I stedet skal vi skape partikler i en Partikler objekt. Vi må slå renderer type fra DisplayObjectRenderer3D til PV3DParticleRenderer   Erklærer følgende variabler for Papervision3D-relaterte gjenstander:   Koden i dokumentet klassens konstruktør er nå:   initPV3D () metoden setter opp Papervision3D Miljø. Her er koden:   Nå Stardust bare oppdaterer 3D-objektenes egenskaper; Papervision3D sin gjengi motoren tar over ansvaret for rendering. Dette er hva vår nye hoved sløyfe ut:   Nå som vi bruker Papervision3D kamera, vil vi også nødt til å endre updateCamera () metode:   Ok, vi har nå byttet fra Stardust innfødt 3D-motor til Papervision3D. La oss nå ta en titt på resultatet. Legg merke til pixelation virkning på partiklene. Det er fordi Papervision3D først trekker vektorobjekter inn bitmaps før du bruker dem som partikkel materialer   Du finner all kildekoden for dette i "02 - Papervision3D Particles".. Mappen   Så langt har vi jobbet med "2D billboards" - flate gjenstander, som papir. Det er mulig å lage "ekte" 3D partikkel objekter, som Papervision3D sin DisplayObject3D stedene. Vi er bare nødt til å bruke en annen initializer. Nå la oss komme ned til den siste delen av denne opplæringen. Vi vil skape røde og blå kube partikler   Vi kommer til å endre initializer om partikkel utseende for siste gang .   Før det, erklærer en LightObject3D variabel i emitter klassen. Vi kommer til å bruke FlatShadeMaterial for DisplayObject3D gjenstander, som krever en lyskilde. Også, erklærer følgende konstanter - vi vil bruke disse som parametere for FlastShadeMaterial, og for å bestemme kuber 'størrelser:   Nå endrer følgende kode i emitter-klasse:   til dette:   Den nye partikkelen utseende vil bli initialisert som røde og blå 3D kuber. Den første konstruktør parameter for PV3DDisplayObject3DClass initializer er den klassen vi ønsker på å bruke for partiklene (så her er det Cube klasse) og den andre parameteren er en rekke konstruktørparametre for dette Cube klassen.   Tidligere fordi vi jobbet med "2D billboards", bare rotasjon om Z-aksen betydde noe. Nå som vi jobber med ekte 3D-objekter, trenger vi å passere tre Tilfeldige objekt referanser til de Rotation3D og Omega3D konstruktører, en for hver akse   Endre følgende kode i emitter klassen.   til dette:   Denne gangen, i stedet for å bruke en Partikler objekt som vår partikkel container, bruker vi en DisplayObject3D som beholderen. Deklarere en variabel for denne beholderen i dokumentet klassen:   Dessuten trenger vi en annen type renderer for å skape partikler i den nye emballasjen. Endre renderer type fra PV3DParticleRenderer til PV3DDisplayObject3DRenderer. Koden i dokumentet klassens konstruktør skal nå se slik ut:   I initPV3D () -funksjonen, har vi nå behov for å initial beholderen variabel og legge den til scenen. Legg disse to linjene til slutten av den funksjonen:   I den updateCamera () -metoden, ønsker vi å gjøre det lett å følge kameraet, så vi har en illusjon om at lyset alltid "skyter" ut fra våre øyne. Endre følgende kode:   til dette:   Nå lyskilden er alltid på samme punkt som kameraet   Jepp, vi er endelig ferdig med denne opplæringen. Ingen flere koding. La oss ta en titt på vår endelige resultatet, med fancy røde og blå 3D kuber   Kildekoden for dette finner du i "Papervision3D DisplayObject3D" -mappen.   arbeidsflyt for å skape 3D-partikkel effekter med Stardust er Konklusjon   Nå har du det grunnleggende, hvorfor ikke gå tilbake til consts opprettet i trinn 6 og leke med dem å se effektene?   Jeg håper denne opplæringen hjelper deg å forstå Stardust mer og gjør deg mer kjent og komfortabel med Stardust arbeidsflyt. Takk for lesing! 
 å få opp komponenter Panel, deretter drar en knapp fra User Interface mappen på scenen. Sett etiketten til "Pause" og gi den navnet "pause_btn". Vi kommer til å bruke denne knappen for å ta pause 3D partikkel effekter, og dermed lar brukerne til å snurre rundt med kameraet for å få en bedre smak av 3D-miljøet 
 
 
 Trinn 4:. Opprett dokument Class 
 
 pakke {import flash.display.Sprite.; public class StarParticles3D strekker Sprite {offentlig funksjon StarParticles () {}}} 
 
 
 3D Initializers og handlinger 
 
 
 
  idv.cjcat.stardust.twoD Bilde:.. inneholder spesifikke elementer for 2D-partikkel effekter 
 
  idv.cjcat.stardust.threeD Bilde:. inneholder spesifikke elementer for 3D partikkel effekter 
 
 
 handling i 3D pakkeoppdateringer partikkel stillinger i 3D-rom i henhold til de hastighetene, akkurat som sin 2D motstykke i 2D pakken,  Flytt 
 handling. 
 
 
 Trinn 5: Utvide Emitter 
 
; inni den, opprette en ny klasse  StarEmitter 
, som utvider Emitter3D Klasse: 
 pakke {import idv.cjcat.stardust.threeD.emitters.Emitter3D; //ikke glem å importere dette! public class StarEmitter strekker Emitter3D {offentlig funksjon StarEmitter (klokke: Klokke) {//passerer klokken objektet til superklassen sin konstruktør super (klokke); }}} 
 
 offentlige Var pausibleActions: CompositeAction; 
 
 Trinn 6: Erklærer Partikkel konstanter 
 
 private static konst LIFE_AVG: Number = 30; private static konst LIFE_VAR: Number = 10; private static konst SCALE_AVG: Number = 1; private static const SCALE_VAR : Number = 0,4; private static konst GROWING_TIME: Number = 5; private static konst SHRINKING_TIME: Number = 10; private static konst SPEED_AVG: Number = 30; private static konst SPEED_VAR: Number = 10; private static konst OMEGA_AVG: Antall = 0; private static konst OMEGA_VAR: Number = 5; private static konst demping: Number = 0,1; 
 
 Trinn 7: The Switch initializer for Particle Vis objektene 
 
 
 //slå initializers for stjernen og sirkel particlesvar doc1: DisplayObjectClass3D = new DisplayObjectClass3D (Star ); Var doc2: DisplayObjectClass3D = new DisplayObjectClass3D (Circle); Var si: SwitchInitializer = new SwitchInitializer ([doc1, doc2], [1, 1]); addInitializer (si); 
 
 Trinn 8: Tilsett Gjenværende Initializers 
 
 
 
 
 
 addInitializer (nytt liv (ny UniformRandom (LIFE_AVG, LIFE_VAR))); addInitializer (ny Scale (ny UniformRandom (SCALE_AVG, SCALE_VAR))); addInitializer (ny Position3D (ny SinglePoint3D ())); addInitializer (ny Velocity3D (ny SphereShell (0, 0, 0, SPEED_AVG , SPEED_VAR))); addInitializer (ny Rotation3D (null, null, ny UniformRandom (0, 180))); addInitializer (ny Omega3D (null, null, ny UniformRandom (OMEGA_AVG, OMEGA_VAR))); 
 
 Trinn 9: Legg Handlinger 
 
 pausibleActions = new CompositeAction (); pausibleActions.addAction (New Age ()); pausibleActions.addAction (ny DeathLife ()); pausibleActions.addAction (ny Move3D ()); pausibleActions.addAction (ny Spin3D ()); pausibleActions.addAction (ny Damping3D (demping)); pausibleActions.addAction (ny ScaleCurve (GROWING_TIME, SHRINKING_TIME)); addAction (pausibleActions); 
 
 Trinn 10: Tilbake The Document Class 
 
 
 privat statisk konst CAMERA_RADIUS: Nummer = 250; privat statisk. konst PARTICLE_RATE: Nummer = 0,5; 
 
 private Var emitter: StarEmitter; private Var klokke: SteadyClock; private Var renderer: DisplayObjectRenderer3D; 
 //skape klokken og emitterclock = new SteadyClock (PARTICLE_RATE); emitter = new StarEmitter (klokke); //vi kan gjøre dette fordi vi ga StarEmitter konstruktør en klokke parameter //skape renderer og emballasjen spritevar container: Sprite = new Sprite (); container.x = 320, container.y = 200; renderer = new DisplayObjectRenderer3D (container ); renderer.addEmitter (emitter); //legger beholderen til stageaddChild (container); //legge på pauseknappen igjen, slik at det er på toppen av containeraddChild (pause_btn); //satt kameraets utgangsposisjonen og directionrenderer .camera.position.set (0, 0, -CAMERA_RADIUS); renderer.camera.direction.set (0, 0, CAMERA_RADIUS); 
 
 Trinn 11: Program pause 
 
 privat funksjon togglePause (e: MouseEvent): void {if (e.target.label == "Pause") {e.target.label = "Gjenoppta"; clock.ticksPerCall = 0; //stoppe klokken emitter.pausibleActions.active = false; //deaktivere emitter handlinger} else {e.target.label = "Pause"; clock.ticksPerCall = PARTICLE_RATE; //starter klokken emitter.pausibleActions.active = true; //reaktivere emitter handlinger}} 
 pause_btn.addEventListener (MouseEvent.CLICK, togglePause); 
 
 Trinn 12: The Main Loop 
 
 privat funksjon mainLoop (e: Hendelses): void {updateCamera (); emitter.step ();} 
 addEventListener (Event.ENTER_FRAME, mainLoop); 
 
 Trinn 13: Oppdatere kameraets posisjon 
 
 
 privat funksjon updateCamera (): void {var theta: Number = 0,02 * (mouseX - 320);. Var phi: Number = 0,02 * (mousey - 200); phi = StardustMath.clamp (phi, -StardustMath.HALF_PI, StardustMath.HALF_PI); var x: Number = CAMERA_RADIUS * Math.cos (theta) * Math.cos (phi); Var y: Number = CAMERA_RADIUS * tak i Math.sin (phi); Var z: Number = CAMERA_RADIUS * tak i Math.sin (theta) * Math.cos (phi); renderer.camera.position.set (x, y, z); renderer.camera.direction.set (-x, -y, -z);} 
 
 
 Milestone. Native Stardust Motor Komplett 
 
 Demo se det på nettet 
 
 
 Tid for Papervision3D 
 
 
 
 
 
 Trinn 14:. Endre display Object initializer 
 
 Var doc1: DisplayObjectClass3D = new DisplayObjectClass3D (Star); Var doc2: DisplayObjectClass3D = new DisplayObjectClass3D (Circle); 
 Var mat1: MovieParticleMaterial = new MovieParticleMaterial (ny stjerne ()); Var mat2: MovieParticleMaterial = ny MovieParticleMaterial (ny sirkel ()); Var doc1: PV3DParticle = new PV3DParticle ([mat1]); Var doc2: PV3DParticle = new PV3DParticle ([mat2]); 
 
 
 
 Trinn 15:. Sett opp Papervision3D Miljø 
 
 
 private Var scene: SceneObject3D; private Var partikler. Partikler; privat Div kamera: Camera3D; private Var opprinnelse: DisplayObject3D; private Var renderEngine: BasicRenderEngine; private Var view: Viewport3D; 
 initPV3D (); //dette er ny klokke = new SteadyClock (PARTICLE_RATE);! emitter = new StarEmitter (klokke); renderer = new PV3DParticleRenderer (partikler); //dette er nytt renderer.addEmitter (emitter);! pause_btn.addEventListener (MouseEvent.CLICK, togglePause); addEventListener (Event.ENTER_FRAME, mainLoop); 
 privat funksjon initPV3D (): void {//oppretter scene scene = new SceneObject3D (); //oppretter Partikler protestere partikler = nye partikler (); //oppretter kameraet og initial sin posisjon kamera = new Camera3D (); camera.position.x = 0; camera.position.y = 0; camera.position.z = -CAMERA_RADIUS; //oppretter et DO3D representerer opprinnelsen opprinnelse = new DisplayObject3D (); origin.x = origin.y = origin.z = 0; //peker kameraet til opprinnelsen camera.target = opprinnelse; scene.addChild (opprinnelse); scene.addChild (partikler); //oppretter gjengi motor og view renderEngine = new BasicRenderEngine (); view = new Viewport3D (640, 400); //legger synsfeltet til scenen addChild (view); //legger på pauseknappen igjen, slik at det er på toppen av synsfeltet addChild (pause_btn);} 
 
 Trinn 16: The New Hoved Loop 
 
 privat funksjon mainLoop (e: Hendelses): void {updateCamera (); emitter.step (); renderEngine.renderScene (scene, kamera, view); //dette er ny} 
 
 Trinn 17: Oppdatere Kamera 
 
 privat funksjon updateCamera (): void {var theta: Number = 0,02 * (mouseX - 320); Var phi: Number = 0,02 * (mousey - 200); phi = StardustMath.clamp (phi, -StardustMath.HALF_PI, StardustMath.HALF_PI); var x: Number = CAMERA_RADIUS * Math.cos (theta) * Math.cos (phi); Var y: Number = -CAMERA_RADIUS * tak i Math.sin (phi); //oppmerksom på at dette er negativt nå Var z: Number = CAMERA_RADIUS * tak i Math.sin (theta) * Math.cos (phi); camera.x = x; //vi oppdaterer hver av x, y, z egenskaper PV3D kamera separat camera.y = y; camera.z = z;} 
 
 Milepæl: Papervision3D med Partikler Utførte 
 
 Demo se det på nettet 
 < hr> 
 Papervision3D sin DisplayObject3D Class 
 
 
 
 Trinn 18:. Endre display Object initializer, 
 Igjen 
 
 offentlig Var lys: LightObject3D; private static konst LIGHT_COLOR_1: uint = 0xCC3300; private static konst LIGHT_COLOR_2: uint = 0x006699; private static konst AMBIENT_COLOR_1: uint = 0x881100; private static konst AMBIENT_COLOR_2: uint = 0x002244; private static konst CUBE_SIZE: Number = 15; 
 Var mat1: MovieParticleMaterial = new MovieParticleMaterial (ny stjerne ()); Var mat2: MovieParticleMaterial = new MovieParticleMaterial (ny sirkel ()); Var doc1: PV3DParticle = new PV3DParticle ([mat1]); Var doc2: PV3DParticle = new PV3DParticle ([mat2]); 
 lys = new LightObject3D (); Var mat1: FlatShadeMaterial = new FlatShadeMaterial (lys, LIGHT_COLOR_1, AMBIENT_COLOR_1); Var mat2: FlatShadeMaterial = new FlatShadeMaterial (lys, LIGHT_COLOR_2, AMBIENT_COLOR_2); Var matList1: MaterialsList = new MaterialsList ({alt: mat1}); Var matList2: MaterialsList = new MaterialsList ({alt: mat2}); Var params1: Array = [matList1, CUBE_SIZE, CUBE_SIZE, CUBE_SIZE]; Var params2: Array = [matList2, CUBE_SIZE , CUBE_SIZE, CUBE_SIZE]; Var doc1: PV3DDisplayObject3DClass = new PV3DDisplayObject3DClass (Cube, params1); Var doc2: PV3DDisplayObject3DClass = new PV3DDisplayObject3DClass (Cube, params2); 
 
 < h2> Trinn 19: De tre dreieakser 
 
 
 AddInitializer ( ny Rotation3D (null, null, ny UniformRandom (0, 180))); addInitializer (ny Omega3D (null, null, ny UniformRandom (OMEGA_AVG, OMEGA_VAR))); 
 Var rotationRandom: UniformRandom = ny UniformRandom (0, 180); Var omegaRandom: UniformRandom = new UniformRandom (OMEGA_AVG, OMEGA_VAR); addInitializer (ny Rotation3D (rotationRandom, rotationRandom, rotationRandom)); addInitializer (ny Omega3D (omegaRandom, omegaRandom, omegaRandom)); 
 
 Trinn 20: Endre dokument Class 
 
 private Var container: DisplayObject3D; 
 initPV3D (); klokke = new SteadyClock (PARTICLE_RATE); emitter = new StarEmitter (klokke); renderer = new PV3DDisplayObject3DRenderer (container); //dette har endret renderer.addEmitter (emitter); pause_btn.addEventListener (MouseEvent.CLICK, togglePause); addEventListener (Event.ENTER_FRAME, mainLoop); 
 
 Trinn 21: Endre initPV3D () Metode 
 
 container = new DisplayObject3D (); scene.addChild (container); 
 
 Trinn 22: Endre updateCamera () Metode 
 
 camera.x = x; camera.y = y; camera.z = z; 
 emitter.light.x = camera.x = x; emitter.light .Y = camera.y = y; emitter.light.z = camera.z = z; 
 
 
 Milestone. Papervision3D med DisplayObject3D Fullført 
 
 Demo se det på nettet! 
 
 < h2> 
 ganske mye den samme som for 2D-effekter. Du bare velger et annet sett med initializers, handlinger og renderers. Stardust støtter også andre 3D-motorer, inkludert ZedBox og ND3D. Bruken er nesten den samme. Du må bare bruke et annet sett med initializers og renderers. Du kan selv forlenge initializer, Handling, og Renderer klasser for å arbeide med hvilken 3D motorer du liker! 
 
 

