Manipulera partikelrörelse med Stardust partikelmotor - Del 2

Detta är den andra delen av denna handledning. Jag ska visa dig hur man kan manipulera partikelrörelse med deflektorer.

Förkunskaper om rörelseunderlag och vektorfält krävs. Jag rekommenderar starkt att du slutför den första delen av denna handledning innan du går vidare.


Slutresultatförhandsvisning

Ta en titt på det slutliga resultatet vi kommer att arbeta för. Det är ett exempel på en golv effekt, med partiklar studsar från golvet.


avvisare

Ganska mycket som gravitation fält, en deflector tar en partikelns nuvarande rörelse data som input. Efteråt överskrider deflektor partikelns rörelse med sin utgång, endast att utmatningen nu innehåller hastighetsdata utöver positionsdata. I 2D-utrymme är således en deflektorens utgång en 4D-vektor; De första två komponenterna i 4D-vektorn representerar x- och y-komponenten i positionsvektorn (betecknad x och y), och de två sista komponenterna representerar hastighetsvektorns x- och y-komponent (betecknad vx och vy).


Hur man använder deflektorer

Kom ihåg det Fält klass och Allvar åtgärder från den första delen av denna handledning? Tja, proceduren är liknande. Du skapar deflektor objekt som manipulerar partikelrörelser och lägg sedan till dem i Avleda, avvika, avlänka åtgärd, precis som du skulle lägga till Fält objekt till Allvar verkan. Låt oss nu titta på ett snabbt exempel.


Golv Effekt

I det här exemplet ska vi använda LineDeflector klass för att skapa en partikel-studsande golv effekt. En linjeavledare simulerar väsentligen en oändligt lång linje i 2D-utrymme, med ena sidan öppet utrymme och den andra sidan fast; partiklar får endast vara i det öppna utrymmet och inte tillåtas i det fria utrymmet. När partiklar kommer från den öppna rymdsidan och slår på linjen kommer de att studsa tillbaka. De Particle.collisionRadius egendom, som representerar partikelns radie, beaktas.

Linjeavledaren använder en normal vektor och en punkt som linjen passerar genom i 2D-utrymme för att bestämma linjen. Här är en illustration som ger dig en bättre idé.


Steg 1: Golvverkets cirkelsymbol

Skapa ett nytt Flash-dokument, dra en cirkel med en radie av 10 och konvertera den sedan till en symbol som exporteras för ActionScript med ett klassnamn Cirkel.


Steg 2: Golvpåverkan Dokumentklassen

Skapa en AS-fil för dokumentklassen. Klassen skapar en emitter och en renderer. Om du tycker om att behöva uppdatera Stardusts grundläggande användning, kan du kolla in den här handledningen.

 paket import flash.display.Sprite; importera flash.events.Event; importera idv.cjcat.stardust.common.emitters.Emitter; importera idv.cjcat.stardust.common.renderers.Renderer; importera idv.cjcat.stardust.twoD.renderers.DisplayObjectRenderer; public class FloorEffect utökar Sprite private var emitter: Emitter; privat var renderer: Renderer; offentlig funktion FloorEffect () emitter = new CircleEmitter (); renderer = ny DisplayObjectRenderer (this); renderer.addEmitter (emitter); addEventListener (Event.ENTER_FRAME, mainLoop);  privat funktion mainLoop (e: Event): void emitter.step (); 

Emitterklassen visas nedan. Det skjuter i princip ut cirkelpartiklar och partiklarna påverkas av ett enhetligt tyngdfält, som pekar nedåt.

 paket import idv.cjcat.stardust.common.actions.Age; importera idv.cjcat.stardust.common.actions.DeathLife; importera idv.cjcat.stardust.common.actions.ScaleCurve; importera idv.cjcat.stardust.common.clocks.SteadyClock; importera idv.cjcat.stardust.common.initializers.Life; importera idv.cjcat.stardust.common.initializers.Scale; importera idv.cjcat.stardust.common.math.UniformRandom; importera idv.cjcat.stardust.twoD.actions.Gravity; importera idv.cjcat.stardust.twoD.actions.Move; importera idv.cjcat.stardust.twoD.emitters.Emitter2D; importera idv.cjcat.stardust.twoD.fields.Field; importera idv.cjcat.stardust.twoD.fields.UniformField; importera idv.cjcat.stardust.twoD.initializers.DisplayObjectClass; importera idv.cjcat.stardust.twoD.initializers.Position; importera idv.cjcat.stardust.twoD.initializers.Velocity; importera idv.cjcat.stardust.twoD.zones.LazySectorZone; importera idv.cjcat.stardust.twoD.zones.SinglePoint; public class CircleEmitter utökar Emitter2D offentlig funktion CircleEmitter () super (new SteadyClock (1)); // initialisatorer addInitializer (nya DisplayObjectClass (Circle)); addInitializer (new Life (new UniformRandom (60, 10))); addInitializer (new Position (new SinglePoint (320, 100))); addInitializer (new Velocity (new LazySectorZone (8, 4))); addInitializer (new Scale (new UniformRandom (1, 0.4))); addInitializer (new CollisionRadius (10)); // åtgärder addAction (new Age ()); addAction (new DeathLife ()); addAction (new Move ()); addAction (ny ScaleCurve (0, 10)); // gravitation var fält: Fält = nytt UniformField (0, 0,5); var gravitation: Gravity = new Gravity (); gravity.addField (fält); addAction (gravitation); 

Nu har du skapat en effekt med partiklar som skjuter ut från mitten av scenen, dras ner av gravitationen. Så här ser det ut:

Milstolpe Visa det på nätet

Steg 3: Golv Effekt Lägg till Deflector

Lägg till folloingskoden i emitterkonstruktorn. Det skapar en linje deflector, lägger den till deflektor åtgärd, och lägger sedan åtgärden till emitteren och därigenom aktiverar deflektor-effekten. De två första konstruktörparametrarna för LineDeflector klassen är koordinaten för en punkt på linjen, och de två sista parametrarna är x- och y-komponenterna i linjens normala vektor. De Deflector.bounce egenskapen bestämmer linjens "bounciness", 1 som orsakar fullständig rebound, och 0 betyder ingen rebound alls.

 // skapa en linje deflektor som passerar genom punkten (320, 320) och normal (0, -1) var deflektor: Deflector = ny LineDeflector (320, 320, 0, -1); deflector.bounce = 0,6; var avböj: Deflect = new Deflect (); deflect.addDeflector (deflektor); addAction (avleda);

Du kan också dra en visuell representation av linjen på scenen för att få en bättre titt.

Okej, vi är färdiga med det här exemplet. Låt oss nu ta en titt på vårt slutliga resultat.

Milstolpe Visa det på nätet

Bounding Box

I det här exemplet ska vi använda BoundingBox deflektor för att begränsa partiklar i en rektangulär yta.


Steg 1: Bindande box Emitterklassen

Dokumentklassen förblir densamma som föregående exempel, men vi kommer att ändra emitterklassen. Detta är basemittersklassen i detta exempel. Jämfört med emitterklassen i det föregående exemplet SteadClock ändras till a ImpulseClock för att omedelbart skapa 20 partiklar i början, ändras positionszonen från en enda punkt till en rektangulär zon som matchar scenstorleken, Hastighet initieraren är långsammare lite, den Liv initieraren avlägsnas eftersom vi vill att partiklar ska stanna permanent på scenen, Ålder och DeathLife Åtgärder är i sin tur inte nödvändiga och borttagna, och ScaleCurve tas också bort. Vissa importeringar läggs också till och tas bort; Du kan bara kopiera koden nedan för att göra det lättare.

 paket import idv.cjcat.stardust.common.clocks.ImpulseClock; importera idv.cjcat.stardust.common.initializers.CollisionRadius; importera idv.cjcat.stardust.common.initializers.Scale; importera idv.cjcat.stardust.common.math.UniformRandom; importera idv.cjcat.stardust.twoD.actions.Deflect; importera idv.cjcat.stardust.twoD.actions.Move; importera idv.cjcat.stardust.twoD.deflectors.BoundingBox; importera idv.cjcat.stardust.twoD.deflectors.Deflector; importera idv.cjcat.stardust.twoD.emitters.Emitter2D; importera idv.cjcat.stardust.twoD.initializers.DisplayObjectClass; importera idv.cjcat.stardust.twoD.initializers.Position; importera idv.cjcat.stardust.twoD.initializers.Velocity; importera idv.cjcat.stardust.twoD.zones.LazySectorZone; importera idv.cjcat.stardust.twoD.zones.RectZone; importera idv.cjcat.stardust.twoD.zones.SinglePoint; public class CircleEmitter utökar Emitter2D private var impulsClock: ImpulseClock; offentlig funktion CircleEmitter () super (impulseClock = nytt impulsklocka (20)); impulseClock.impulse (); // initialisatorer addInitializer (nya DisplayObjectClass (Circle)); addInitializer (ny position (ny RectZone (0, 0, 640, 400))); addInitializer (new Velocity (new LazySectorZone (3, 2))); addInitializer (new Scale (new UniformRandom (1, 0.4))); addInitializer (new CollisionRadius (10)); // åtgärder addAction (new Move ()); 

Steg 2: Bounding Box Lägg till Deflector

Nästan som föregående exempel lägger vi nu till följande kod i emitterkonstruktorn för att använda Avleda, avvika, avlänka åtgärd, bara den här gången använder vi BoundingBox deflektor för att begränsa partiklar i en rektangulär region som matchar scenstorleken.

 // deflektorvarv deflektor: Deflector = ny BoundingBox (0, 0, 640, 400); var avböj: Deflect = new Deflect (); deflect.addDeflector (deflektor); addAction (avleda);

Steg 3: Bounding Box Testa filmen

Det är allt. Ingenting mycket förändras, och nu har vi begränsat partiklar i en avgränsningslåda. Testa filmen och du ska se resultatet.

Milstolpe Visa det på nätet

Custom Deflectors

Nu ska vi skapa egna deflektor på egen hand. Låt oss först förstå deflektor klass vi håller på att utöka.

De deflektor klassen är basklassen för alla deflektorer. För att skapa anpassade deflectorer ska du förlänga den här klassen och åsidosätta calculateMotionData4D () metod, och returnera sedan a MotionData4D objekt som representerar 4D-vektorutgången hos deflektorn. Ingången till ditt förfogande, precis som Fält klass, ingår i Particle2D objektet passerade in i metoden som parameter. Du kan använda det här Particle2D objekt för att bestämma din produktion. Förresten, om denna metod returnerar a null värde, den Avleda, avvika, avlänka åtgärd antar att du inte vill ändra den aktuella partikelns rörelse, ignorera partikeln och fortsätt sedan bearbeta nästa partikel.

Till exempel skulle följande deflektor rotera varje partikelhastighetsvektor med en grad klockvis.

 paket import idv.cjcat.stardust.twoD.geom.Vec2D; importera idv.cjcat.stardust.twoD.particles.Particle2D; importera idv.cjcat.stardust.twoD.deflectors.Deflector; importera idv.cjcat.stardust.twoD.geom.MotionData4D; allmän klass Rotator sträcker Deflector överstyr skyddad funktion calculateMotionData4D (partikel: Particle2D): MotionData4D varhastighet: Vec2D = ny Vec2D (particle.vx, particle.vy); velocity.rotateThis (1); returnera nya MotionData4D (partikel.x, partikel.y, hastighet.x, hastighet.y); 

Tube Deflector Effect

I det här exemplet kommer vi att förlänga deflektor klass och skapa vår egen deflector, simulera ett rör, som i huvudsak är två linjedämpare som smälter i ett rörformat ledigt utrymme.


Steg 1: Tube Deflector Effect Emitterklassen

Kopiera Flash-dokumentet, tillsammans med Cirkel symbol och dokumentet från det första exemplet. Här kommer vi att skapa en annan emittersklass, som fortfarande heter CircleEmitter. Den här gången sänder emitteren partiklar från centrum av scenen och ingen gravitation fält appliceras.

 paket import idv.cjcat.stardust.common.actions.Age; importera idv.cjcat.stardust.common.actions.DeathLife; importera idv.cjcat.stardust.common.actions.ScaleCurve; importera idv.cjcat.stardust.common.clocks.SteadyClock; importera idv.cjcat.stardust.common.initializers.CollisionRadius; importera idv.cjcat.stardust.common.initializers.Life; importera idv.cjcat.stardust.common.initializers.Scale; importera idv.cjcat.stardust.common.math.UniformRandom; importera idv.cjcat.stardust.twoD.actions.Deflect; importera idv.cjcat.stardust.twoD.actions.Move; importera idv.cjcat.stardust.twoD.deflectors.Deflector; importera idv.cjcat.stardust.twoD.emitters.Emitter2D; importera idv.cjcat.stardust.twoD.initializers.DisplayObjectClass; importera idv.cjcat.stardust.twoD.initializers.Position; importera idv.cjcat.stardust.twoD.initializers.Velocity; importera idv.cjcat.stardust.twoD.zones.LazySectorZone; importera idv.cjcat.stardust.twoD.zones.SinglePoint; public class CircleEmitter utökar Emitter2D offentlig funktion CircleEmitter () super (new SteadyClock (1)); // initialisatorer addInitializer (nya DisplayObjectClass (Circle)); addInitializer (new Life (new UniformRandom (60, 10))); addInitializer (new Position (new SinglePoint (320, 200))); // stadium center addInitializer (ny hastighet (nya LazySectorZone (8, 4))); addInitializer (new Scale (new UniformRandom (1, 0.4))); addInitializer (new CollisionRadius (10)); // åtgärder addAction (new Age ()); addAction (new DeathLife ()); addAction (new Move ()); addAction (ny ScaleCurve (0, 10)); 

Steg 2: Tube Deflector Effekt Tube Deflector

Nu ska vi skapa vår tube deflector klass. Detaljerna förklaras i kommentarer.

 paket import idv.cjcat.stardust.twoD.particles.Particle2D; importera idv.cjcat.stardust.twoD.deflectors.Deflector; importera idv.cjcat.stardust.twoD.geom.MotionData4D; public class TubeDeflector sträcker Deflector private var y1: Number; privat var y2: nummer; offentlig funktion TubeDeflector (y1: Number, y2: Number) // y2 bör vara större än y2 om (y1> y2) // byt y1 och y2 om y1 är större var temp: Number = y1; y1 = y2; y2 = temp;  this.y1 = y1; this.y2 = y2;  åsidosätta skyddad funktion calculateMotionData4D (partikel: Particle2D): MotionData4D // utgångskomponenter, initialiserade till partikelns ursprungliga rörelsesdata var x: Number = particle.x; var y: Number = particle.y; var vx: Number = particle.vx; var vy: Number = particle.vy; // kaluculera den faktiska kollisionsradien var radie: Number = particle.collisionRadius * particle.scale; // flagga för huruvida deflektorn träder i kraft var avböjt: Booleskt = false; om (partikel.y < (y1 + radius))  //particle y-coordinate is less than lower limit //set proper new y-coordinate y = y1 + radius; //set flag deflected = true;  else if (particle.y > (y2-radie)) // partikel y-koordinat är större än övre gräns // Ange korrekt ny y-koordinat y = y2-radie; // set flaggböjde = true;  om (avböjt) returnera nya MotionData4D (x, y, vx, vy);  annars // ignorerar partikeln och uppdaterar inte sin rörelsedata retur null; 

Steg 3: Tube Deflector Effect Lägg till Deflector

Du borde veta vad vi ska göra nu mycket bra nu. Det är rätt, vi ska lägga till deflektorn till en Avleda, avvika, avlänka åtgärd och lägg sedan till åtgärden till emitern. Lägg till följande kod i emitterkonstruktorn.

 // skapa en rör deflektor var deflector: Deflector = ny TubeDeflector (100, 300); var avböj: Deflect = new Deflect (); deflect.addDeflector (deflektor); addAction (avleda);

Steg 4: Tube Deflector Effect Testa filmen

Nu kan du testa filmen. Återigen kan du också dra en viss visuell representation av deflektorn på scenen för en bättre utseende.

Milstolpe Visa det på nätet

Slutsats

Detta är slutet på hela handledningen. I den första delen har du lärt dig om gravitationsfält. I den andra delen har du lärt dig begreppet deflectorer och den faktiska användningen av Avleda, avvika, avlänka verkan. Du har också lärt dig hur du förlänger deflektor klass för att skapa anpassade deflectorer. Nu kan du utföra avancerad partikelrörelsesmanipulation i Stardust.

Tack så mycket för att du läser!