Schieße Sterne mit der Stardust Particle Engine ab

In diesem Tutorial werde ich Ihnen die Stardust Particle Engine vorstellen. Zuerst werde ich Ihnen zeigen, wie Sie Stardust einrichten, und dann werde ich die grundlegenden Verantwortlichkeiten der Stardust-Klasse abdecken und wie sie zusammenarbeiten, damit Stardust als Ganzes funktioniert.

Als Nächstes betrachten wir den allgemeinen Arbeitsablauf eines Stardust und erstellen einen Partikeleffekt, bei dem Sterne aus dem Mauszeiger herausschießen. Die Sterne verlangsamen sich allmählich, werden nach der Geburt größer und schrumpfen beim Sterben.

Abschließend möchte ich die Flexibilität von Stardust demonstrieren, indem ich verschiedene Variationen des bereits vollständigen Beispiels verwende, einschließlich der Verwendung von animierten Movieclips als Partikel, einer Zeitskala mit variablen Partikelsimulationen und dem Herausnehmen von Anzeigeobjekten verschiedener Klassen mit einem einzigen Emitter.

Dieses Tutorial richtet sich an Personen, die bereits mit der objektorientierten Programmierung von ActionScript 3.0 (OOP) vertraut sind. Ich gehe also davon aus, dass Sie bereits sehr gut wissen, was Klassen, Objekte, Vererbung und Schnittstelle bedeuten. Kein Problem mit OOP? Dann lass uns ein paar Sterne schießen!




Sternenstaub-Partikelmotor

Wie der Name schon sagt, wird Stardust zur Erzeugung von Partikeleffekten verwendet. Wenn Sie ein erfahrener ActionScripter sind, haben Sie möglicherweise oft Partikeleffekte von Grund auf neu erstellt und sagen "Ich bin total cool, Partikeleffekte von Grund auf zu erzeugen. Warum brauche ich dann eine Partikelmaschine?" Nun, Stardust hilft Ihnen dabei, sich mehr auf das tatsächliche Verhalten des Partikelverhaltens zu konzentrieren, als sich um die langweiligen Dinge zu kümmern, die sich auf niedriger Ebene befinden, wie etwa das Speichermanagement. Anstatt Code für die Partikeldaten zu schreiben, Ressourcen zu initialisieren und zu entsorgen, können Sie mit Stardust diese langweiligen Routinen überspringen und entscheiden, wie sich Ihre Partikel verhalten sollen.

Stardust-Funktionen

Die Klassenstruktur von Stardust wurde von FLiNT Particle System, einer weiteren ActionScript 3.0-Partikel-Engine, inspiriert. Daher haben sie einige ähnliche Grundfunktionen.

  • 2D- und 3D-Partikeleffekte - Mit Stardust können sowohl 2D- als auch 3D-Partikeleffekte erstellt werden. Es verfügt über eine eigene integrierte 3D-Engine und kann auch verwendet werden, um mit anderen 3D-Engines mit Drittpartikeln, einschließlich ZedBox, Papervision3D und ND3D, zu arbeiten.
  • Hohe Erweiterbarkeit - Stardust stellt Ihnen eine große Anzahl von Partikelverhalten und Renderern zur Verfügung. Wenn keine davon Ihren Anforderungen entspricht, können Sie die Basisklassen jederzeit erweitern und Ihre eigenen benutzerdefinierten Partikelverhalten erstellen. Sie können auch einen eigenen Renderer erstellen, um mit einer anderen 3D-Engine zu arbeiten, die nicht von Stardust unterstützt wird.

Neben diesen grundlegenden Funktionen bietet Stardust auch einige erweiterte Funktionen für erfahrene Benutzer.

  • Einstellbare Simulationszeitskala - Die für die Partikelsimulation verwendete Zeitskala kann während der Laufzeit dynamisch angepasst werden. Wenn Sie beispielsweise die Zeitskala auf die Hälfte des Originals ändern, ist der Partikeleffekt halb so schnell wie die normale Geschwindigkeit. und wenn Sie die Zeitskala auf das Doppelte des Originals einstellen, wird der Partikeleffekt doppelt so schnell wie normal simuliert. Diese Funktion kann nützlich sein, wenn Sie ein Spiel mit Zeitlupeneffekten erstellen: Der Partikeleffekt kann langsamer werden, um sich an die Geschwindigkeit Ihrer Spiel-Engine anzupassen, und wird mit Ihrer Spielanimation und -grafik synchronisiert.
  • XML-Serialisierung - Sie können Ihr Partikelsystem in eine Datei im XML-Format umwandeln, die Sie auf Ihrer Festplatte speichern, später während der Laufzeit laden und interpretieren können, um Ihr Original-Partikelsystem zu rekonstruieren. Dies ist sehr nützlich, wenn Sie mit einem großen Projekt arbeiten. Angenommen, Sie möchten Ihre Partikel nur ein wenig verkleinern, so dass Sie die Parameter im Quellcode anpassen und Ihre gesamte Flash-Anwendung neu kompilieren. Dies kann eine Minute oder sogar fünf Minuten dauern, wenn Ihr Projekt sehr umfangreich ist. Ist es das wert? Definitiv nein. Das ist eine totale Zeitverschwendung. Mit der XML-Serialisierungsfunktion zum Speichern Ihres Partikelsystems in externen XML-Dateien trennen Sie Parameter vom Quellcode für die Hauptanwendung. Sie müssen also lediglich die XML-Datei öffnen, die Parameterwerte ändern, speichern und die Hauptanwendung erneut öffnen. Das ist es! Es ist keine Neukompilierung erforderlich. Ich würde sagen, dass dies der ideale Weg ist, um mit großen Projekten zu arbeiten.

Bei Partikeleffekten ist es sehr wichtig, mit massiven Partikeldaten effizient umzugehen. Stardust nutzt häufig Objektpools und verknüpfte Listen, um die Leistung zu verbessern:

  • Objektpools - Gebrauchte Objekte werden in einem Pool gespeichert. Wenn später ein Objekt desselben Typs benötigt wird, instanziiert Stardust es nicht sofort, sondern prüft, ob zuvor ein Objekt im Objektpool vorhanden ist. Wenn ja, nimmt Stardust das Objekt einfach heraus und verwendet es, anstatt ein ganz neues Objekt zu erstellen. Normalerweise erfordern Partikeleffekte viel Objektinstanzierung, was CPU-aufwendig ist. Durch die Verwendung von Objektpools reduziert Stardust den Instantiierungsaufwand erheblich.
  • Verknüpfte Listen - Es ist sehr einfach und verlockend, Partikeldaten in einem Array zu speichern. Wenn jedoch sehr häufig Partikel erzeugt und entfernt werden, findet viel Array-Splicing statt, um tote Partikel zu entfernen. Array-Splicing ist insbesondere für lange Arrays ein CPU-aufwendiger Prozess. Für eine verkettete Liste, egal wie lang die Liste ist, dauert es immer genauso lange, um tote Partikel auszuspleißen. Seit der Version 1.1 verwendet Stardust intern verknüpfte Listen zum Speichern von Partikeldaten.

Stardust einrichten

Bevor wir mit der eigentlichen Codierung beginnen, müssen wir uns eine Kopie von Stardust Particle Engine besorgen. Es ist unter der MIT-Lizenz veröffentlicht, was bedeutet, dass es völlig kostenlos ist, unabhängig davon, ob Sie es in einem kommerziellen oder nicht-kommerziellen Projekt verwenden möchten.

Hier ist die Projekt-Homepage von Stardust: http://code.google.com/p/stardust-particle-engine/

Sie können Stardust hier herunterladen: http://code.google.com/p/stardust-particle-engine/downloads/list

Zum Zeitpunkt des Schreibens ist 1.1.132 Beta die neueste Version, die von der Downloadliste heruntergeladen werden kann. Sie können immer die neueste Version aus dem SVN-Repository beziehen (die jedoch möglicherweise nicht stabil ist)..

Auf der Projekthomepage finden Sie auch weiteres Zubehör wie die API-Dokumentation und eine Kopie des PDF-Handbuchs. Es gibt sogar Video-Tutorials auf YouTube.

Stardust-Klassenverpflichtungen

Ich werde hier kurz auf die Kernklassen von Stardust und ihre Verantwortlichkeiten eingehen.

StardustElement

Diese Klasse ist die Oberklasse aller Kernklassen, die Eigenschaften und Methoden speziell für die XML-Serialisierung definiert.

Zufällig

Im Allgemeinen geht es bei Partikeleffekten darum, eine Anzahl von Objekten mit ähnlichem, aber randomisiertem Aussehen und Verhalten zu steuern. Die Random-Klasse dient zum Generieren von Zufallszahlen, die in Stardust zur Randomisierung von Partikeleigenschaften verwendet werden können. Zum Beispiel ist die UniformRandom-Klasse eine Unterklasse der Random-Klasse. Der Name sagt alles aus: Die von einem UniformRandom-Objekt generierte Zufallszahl ist gleichmäßig verteilt, und ich werde diese Klasse insbesondere für das gesamte Lernprogramm verwenden.

Zone

Es gibt Zeiten, in denen eine eindimensionale Zufallszahl nicht ausreicht. Manchmal benötigen wir zweidimensionale Zufallszahlen, die im Wesentlichen Paare von Zufallszahlen sind, für Eigenschaften wie Position und Geschwindigkeit. Die Zone-Klasse dient zum Erzeugen von zweidimensionalen Zufallszahlenpaaren. Diese Klasse modelliert ein Zufallszahlenpaar als zufälligen Punkt in einer 2D-Zone. Beispielsweise generiert die CircleZone Zufallszahlenpaare (x, y) aus zufälligen Punkten innerhalb eines kreisförmigen Bereichs. Die Klassen Random und Zone werden hauptsächlich von der Klasse Initializer verwendet, die später behandelt wird. Die Zone3D-Klasse ist das 3D-Gegenstück dieser Klasse für 3D-Partikeleffekte.

Emitter

In der Emitter-Klasse werden im Grunde alle Low-Level-Sachen gekapselt. Ein Emitter initialisiert neu erstellte Partikel, bevor sie in die Simulation eingefügt werden, aktualisiert die Partikeleigenschaften in jeder Iteration der Hauptschleife und entfernt abgestorbene Partikel aus der Simulation. Die Emitter.step () -Methode ist das, was Sie wiederholt aufrufen möchten, um Stardust am Laufen zu halten.

Uhr

Die Clock-Klasse bestimmt die Rate der Erzeugung neuer Partikel für Emitter. Ein Emitter-Objekt enthält genau eine Referenz auf ein Clock-Objekt. Am Anfang jedes Emitter.step () - Methodenaufrufs fragt der Emitter das Uhrobjekt, wie viele neue Partikel es erstellen soll. Nehmen Sie zum Beispiel die SteadyClock-Klasse. Sie weist die Emitter an, mit konstanter Geschwindigkeit neue Partikel zu erstellen.

Initialisierer

Diese Klasse dient zum Initialisieren von neu erstellten Partikeln. Ein Initialisierungsobjekt muss zu einem Emitter hinzugefügt werden, damit es funktioniert. Grundsätzlich initialisiert eine Initializer-Unterklasse nur eine Partikeleigenschaft. Beispielsweise initialisiert die Masseninitialisierungsklasse die Masse neuer Partikel. Einige Initialisierer akzeptieren ein Random-Objekt als Konstruktorparameter zum Initialisieren von Partikeln mit randomisierten Werten. Der folgende Code erstellt einen Lebensinitialisierer, der die Lebensdauer der Partikel auf Werte zentriert, die bei 50 mit einer Variation von 10, nämlich im Bereich von 40 bis 60, zentriert sind.

 neues Leben (neues UniformRandom (50, 10));

Aktion

Aktionsobjekte aktualisieren die Partikeleigenschaften in jeder Iteration der Hauptschleife (die Methode Emiter.step ()). Beispielsweise aktualisiert die Aktionsklasse Move die Partikelpositionen entsprechend der Geschwindigkeit. Ein Aktionsobjekt muss zu einem Emitter hinzugefügt werden, damit es funktioniert.

Allgemeiner Stardust-Workflow

Nun, da Sie wissen, wie die Kernklassen zusammenarbeiten, werfen wir einen Blick auf den allgemeinen Arbeitsablauf für Stardust.

Sie beginnen mit der Erstellung eines Senders. Verwenden Sie die Emitter2D-Klasse für 2D-Partikeleffekte und die Emitter3D-Klasse für 3D-Effekte.

 Var-Emitter: Emitter = neuer Emitter2D ();

Um die Rate der Partikelerzeugung festzulegen, benötigen wir eine Uhr. Dies kann entweder durch die Emitter.clock -Eigenschaft festgelegt werden, oder durch Übergabe einer Uhr als ersten Parameter an den Konstruktor des Emitters.

 // Eigenschaftsansatz emitter.clock = new SteadyClock (1); // Konstruktoransatz var emitter: Emitter = new Emitter2D (new SteadyClock (1));

Fügen Sie dem Emitter über die Emitter.addInitializer () - Methode Initialisierer hinzu.

 emitter.addInitializer (neues Leben (neues UniformRandom (50, 10))); emitter.addInitializer (neue Skala (neues UniformRandom (1, 0.2)));

Fügen Sie dem Emitter über die Emitter.addAction () - Methode Aktionen hinzu.

 emitter.addAction (new Move ()); emitter.addAction (neuer Spin ());

Erstellen Sie einen Renderer, und fügen Sie den Emitter über die Renderer.addEmitter () - Methode dem Renderer hinzu.

 var-Renderer: Renderer = neuer DisplayObjectRenderer (Container); // "container" ist unser container sprite renderer.addEmitter (emitter);

Rufen Sie schließlich wiederholt die Emitter.step () -Methode auf, um die Partikelsimulation aufrechtzuerhalten. Möglicherweise möchten Sie dazu das Enter-Frame-Ereignis oder einen Timer verwenden. In einem einzigen Aufruf der Methode Emitter.step () bestimmt die Uhr, wie viele neue Partikel erstellt werden sollen. Diese neuen Partikel werden durch Initialisierer initialisiert, alle Partikel werden durch Aktionen aktualisiert, tote Partikel werden entfernt, und der Renderer rendert den Renderer der Partikeleffekt.

 // Enter-Frame-Ereignisansatz addEventListener (Event.ENTER_FRAME, mainLoop); // timer approach timer.addEventListener (TimerEvent.TIMER, mainLoop); Funktion mainLoop (e: Event): void emitter.step (); 

In Ordung. Das ist so ziemlich alles für Stardust Primer. Nun ist es Zeit, die Flash IDE zu öffnen und sich die Hände schmutzig zu machen.

Schritt 1: Erstellen Sie ein neues Flash-Dokument

Erstellen Sie ein neues Flash-Dokument mit einer Größe von 640X400, einer Bildrate von 60 Bildern pro Sekunde und einem dunklen Hintergrund. Hier habe ich einen dunkelblauen Hintergrund mit Farbverlauf gemacht. Stardust funktioniert übrigens gut mit Flash Player 9 und 10, also ist es in Ordnung, egal, ob Sie Flash CS3 oder CS4 verwenden. In diesem Tutorial verwende ich Flash CS3.

Schritt 2: Zeichnen Sie einen Stern

Wir erzeugen einen Partikeleffekt mit Sternen. Daher müssen wir einen Stern zeichnen und in ein Symbol konvertieren, das natürlich für ActionScript exportiert wird. Dieses Symbol wird später verwendet, um unseren Partikeleffekt wiederzugeben. Benennen Sie das Symbol und die exportierte Klasse "Stern"..

Schritt 3: Erstellen Sie die Dokumentenklasse

Erstellen Sie eine neue Dokumentenklasse und nennen Sie sie StarParticles.

 package import flash.display.Sprite; öffentliche Klasse StarParticles erweitert Sprite öffentliche Funktion StarParticles () 

Schritt 4: Verlängern Sie den Emitter

Wie im allgemeinen Arbeitsablauf erwähnt, besteht der erste Schritt darin, einen Emitter zu erstellen. Der nächste Schritt besteht darin, dem Emitter Initialisierer und Aktionen hinzuzufügen. Obwohl dies im Dokumentklassenkonstruktor möglich ist, empfehle ich dringend, dies in einer separaten Emitter-Unterklasse durchzuführen. Es ist immer besser, das Partikelverhalten vom Hauptprogramm zu trennen. Dadurch ist der Code in Zukunft wesentlich sauberer und leichter zu ändern, ohne mit dem Hauptprogramm verwechselt zu werden.

Wir werden einen 2D-Partikeleffekt erzeugen, daher ist Emitter2D die Emitterklasse, die wir erweitern möchten. Erweitern Sie die Emitter2D-Klasse und nennen Sie sie StarEmitter, da wir später Sterne herausschießen lassen. Der Emitterkonstruktor akzeptiert einen Clock-Parameter. Daher deklarieren wir einen Konstruktorparameter, der eine Clock-Objektreferenz an den Konstruktor der Superklasse weitergibt.

 Paket import idv.cjcat.stardust.twoD.emitters.Emitter2D; public class StarEmitter erweitert Emitter2D public function StarEmitter (clock: Clock) // das Clock-Objekt an den Konstruktor der Superklasse übergeben super (clock); 

Schritt 5: Konstanten deklarieren

Ein besserer Ansatz zum Erstellen einer Emitter-Unterklasse besteht darin, Partikelparameter als statische Konstanten an einem Ort zu gruppieren. Wenn Sie also die Parameter anpassen möchten, wissen Sie immer, wo Sie die Deklarationen finden. Die Bedeutung dieser Konstanten wird später erläutert, wenn sie verwendet werden.

 // durchschnittliche Lebensdauer privates statisches const LIFE_AVG: Number = 30; // Lebensdaueränderung private statische const LIFE_VAR: Number = 10; // durchschnittliche Skala private statische Konstante SCALE_AVG: Number = 1; // Skalierungsvariation privates statisches const SCALE_VAR: Number = 0.4; // Skalierungswachstumszeit private static const GROWING_TIME: Number = 5; // Skalierzeit für die Verkleinerung private statische const SHRINKING_TIME: Number = 10; // durchschnittliche Geschwindigkeit private static const SPEED_AVG: Number = 10; // Geschwindigkeitsänderung private static const SPEED_VAR: Number = 8; // Durchschnitt Omega (Winkelgeschwindigkeit) private statische Konstante OMEGA_AVG: Number = 0; // Omega-Variation private statische Konstante OMEGA_VAR: Number = 5; // Dämpfungskoeffizient private statische Konstante DAMPING: Number = 0.1;

Schritt 6: Initialisierer hinzufügen

Welche Initialisierer brauchen wir, um unseren Partikeleffekt zu erzeugen? Schauen wir uns die folgende Liste an:

  • DisplayObjectClass - Dieser Initialisierer weist jedem Partikel ein bestimmtes Anzeigeobjekt zu, das von einem DisplayObjectRenderer zum Rendern von Partikeleffekten verwendet wird. Der Konstruktor akzeptiert eine Klassenreferenz auf die Anzeigeobjektklasse, die wir instanziieren möchten. Für dieses Tutorial ist diese Klasse die Sternenklasse (Symbol), die wir in Schritt 2 erstellt haben.
  • Leben - Dieser Initialisierer weist jedem Partikel einen zufälligen Lebensdauerwert zu. Später fügen wir dem Emitter Aktionen hinzu, um diesen Lebenswert im Laufe der Zeit zu verbrauchen und ein Teilchen als tot zu markieren, wenn sein Lebenswert Null erreicht. Ein Zufallsobjekt wird an den Konstruktor übergeben, der von diesem Initialisierer verwendet wird, um einen Zufallswert für die Lebensdauer der Partikel zu generieren. In den meisten Fällen ist die UniformRandom-Klasse praktisch und ausreichend. Der erste Parameter des UniformRandom-Konstruktors ist der Mittelpunkt (oder Durchschnittswert) der erzeugten Zufallszahlen und der zweite ist der Radius (oder die Variation). Beispielsweise erzeugt ein UniformRandom-Objekt mit der Mitte 20 und der Variation 5 Zufallszahlen innerhalb des Bereichs [15, 25]. Hier verwenden wir die LIFE_AVG-Konstante für den Mittelwert und LIFE_VAR für den Radius.
  • Rahmen - Wie der Life-Initialisierer initialisiert der Skalierungs-Initialisierer die Skalierung eines Partikels mit einem Zufallswert, der durch ein Zufallsobjekt bestimmt wird, das an den Konstruktor des Initialisierers übergeben wird. Hier verwenden wir die SCALE_AVG-Konstante für den Mittelwert und SCALE_VAR für den Radius.
  • Position - Dieser Initialisierer weist einem Partikel eine zufällige Position zu. Im Gegensatz zu den Life- und Scale-Initialisierern, die nur 1D-Zufallszahlen benötigen, benötigt der Positions-Initialisierer 2D-Zufallszahlengeneratoren. Wie im Abschnitt Zuständigkeiten der Stardust-Klasse beschrieben, ist die Zone-Klasse genau für diesen Zweck. Das an den Konstruktor des Initialisierers übergebene Zone-Objekt wird zur Erzeugung von 2D-Zufallszahlenpaaren verwendet, die Partikeln als Positionsvektoren zugewiesen werden. In diesem Lernprogramm werden Sterne von einem einzelnen Punkt aus, der sich am Mauszeiger befindet, herausgeschossen. Daher verwenden wir eine SinglePoint-Klasse, eine Zone-Unterklasse. Um die Koordinate dieses SinglePoint-Objekts von der Dokumentklasse aus dynamisch anzupassen, müssen Sie einen Verweis auf dieses Punktobjekt über eine öffentliche Eigenschaft verfügbar machen. Dafür gibt es die "Point" -Eigenschaft.
  • Geschwindigkeit - Wie der Positionsinitialisierer benötigt der Velocity-Initialisierer ein Zone-Objekt, um 2D-Zufallswertepaare zum Initialisieren der Teilchengeschwindigkeit zu erzeugen. Ein vom Zone-Objekt erzeugter 2D-Vektor, der die Koordinate eines zufälligen Punkts in der Zone ist, wird Partikeln als Geschwindigkeiten zugewiesen. Hier verwenden wir die LazySectorZone-Klasse, die eine Sektorregion darstellt. Ein Sektor ist ein Teil eines Kreises, der von zwei Radien und zwei Winkeln eingeschlossen ist. Bei der LazySectorZone sind die beiden Winkel standardmäßig 0 und 360, was einen vollen Winkel um einen Kreis darstellt. Der erste Konstruktorparameter der LazySectorZone-Klasse ist der Durchschnitt der zwei Radien und der zweite ist die Variation der Radien. In diesem Fall repräsentiert der Durchschnitt der beiden Radien die Durchschnittsgeschwindigkeit und die Variation der Radien die Variation der Geschwindigkeit. Hier verwenden wir die SPEED_AVG-Konstante für den ersten Parameter und SPEED_VAR für den zweiten.
  • Drehung - Der Rotationsinitialisierer initialisiert den Rotationswinkel eines Partikels auf einen zufälligen Wert. Als einige der oben genannten Initialisierer akzeptiert der Konstruktor ein Zufallsobjekt, um einen Zufallswert zu erzeugen. Da wir Teilchen mit Winkeln zwischen 0 und 360 Grad wünschen, verwenden wir 0 als Mittelpunkt und 180 als Radius des UniformRandom-Objekts.
  • Omega - Omega bedeutet, wie in den meisten Physiklehrbüchern, Winkelgeschwindigkeit. Damit ist der Zweck dieses Initialisierers klar: Er initialisiert die Winkelgeschwindigkeit eines Partikels mit einem zufälligen Wert, und die OMEGA_AVG-Konstante wird als Mittelpunkt und OMEGA_VAR als Radius des UniformRandom-Objekts verwendet.

Und hier ist der Code:

 Punkt = neuer SinglePoint (); addInitializer (new DisplayObjectClass (Star)); addInitializer (new Life (neues UniformRandom (LIFE_AVG, LIFE_VAR))); addInitializer (new Scale (neues UniformRandom (SCALE_AVG, SCALE_VAR))); addInitializer (neue Position (Punkt)); addInitializer (neue Geschwindigkeit (neue LazySectorZone (SPEED_AVG, SPEED_VAR)))); addInitializer (neue Rotation (neues UniformRandom (0, 180))); addInitializer (neues Omega (neues UniformRandom (OMEGA_AVG, OMEGA_VAR)));

Schritt 7: Aktionen hinzufügen

Okay, wir sind mit den Initialisierern fertig. Jetzt ist es Zeit, dem Emitter Aktionen hinzuzufügen. Nachfolgend finden Sie eine Liste von Aktionen, die wir benötigen:

  • Alter - Die Aktion Alter verringert den Lebenswert eines Partikels in jedem Emitterschritt um 1.
  • Tod Leben - Wenn der Lebenswert eines Partikels null erreicht, markiert diese Aktion das Partikel als tot und ändert seine isDead-Eigenschaft von false in true. Am Ende eines Emitterschritts werden abgestorbene Partikel entfernt.
  • Bewegung - Wie der Name schon sagt, aktualisiert die Aktion "Bewegung" die Partikelpositionen entsprechend ihren Geschwindigkeiten.
  • Dreh - Ähnlich wie bei der Aktion "Bewegung" aktualisiert die Spin-Aktion den Rotationswinkel eines Partikels entsprechend dem Omega-Wert des Partikels (Winkelgeschwindigkeit)..
  • Dämpfung - Diese Aktion multipliziert die Geschwindigkeit eines Partikels mit einem Faktor im Bereich [0, 1], der Dämpfungseffekte simuliert und das Partikel allmählich verlangsamt. Ein Faktor von 1 bedeutet keine Dämpfung: Partikel bewegen sich frei, als gäbe es keinen Dämpfungseffekt; Ein Faktor von Null bedeutet Gesamtdämpfung: Alle Partikel können sich nicht ein bisschen bewegen. Dieser Faktor wird durch den "Dämpfungskoeffizienten" durch diese Formel bestimmt: "Faktor = 1 - (Dämpfungskoeffizient)". Der an den Konstruktor übergebene Parameter ist der Dämpfungskoeffizient. Hier wollen wir nur einen kleinen Dämpfungseffekt, also verwenden wir den Wert 0,1 für den Koeffizienten.
  • ScaleCurve - Die Aktion ScaleCurve ändert die Skalierung eines Partikels entsprechend seinem Lebenswert. Nach der Geburt wächst sie von einer anfänglichen Skala zu einer normalen Skala und verschwindet nach ihrem Tod auf einer endgültigen Skala. Natürlich kann ein Partikel auch einen anfänglichen oder endgültigen Skalenwert haben, der größer als der normale Maßstab ist. es hängt nur von der persönlichen Wahl ab. In vielen Fällen möchten wir, dass die Partikel einen anfänglichen und einen endgültigen Skalenwert von Null haben, was der Standardwert ist. Der erste Parameter im Konstruktor steht für die Wachstumszeit eines Partikels, und der zweite ist die Abklingzeit. Daher übergeben wir die Konstanten GROWING_TIME und SHRINKING_TIME als ersten bzw. zweiten Parameter. Die Wachstumszeit beträgt 5, was bedeutet, dass ein Partikel während der ersten fünf Lebensdauereinheiten von der Nullskala zur normalen Skala wächst. und die Schrumpfungszeit beträgt 15, was bedeutet, dass ein Partikel bei der letzten 15 Einheit der Lebensdauer auf eine Skala von Null schrumpft. Beachten Sie, dass der Übergang standardmäßig linear ist, aber es können beliebige Beschleunigungsfunktionen verwendet werden, insbesondere die von Robert Penner erstellten Beschleunigungsgleichungen. Es gibt eine andere ähnliche Aktion namens AlphaCurve, was auf Alpha-Werte auf die gleiche Weise funktioniert.

Das ist es. Unser Emitter ist fertig. Hier ist der Code für diesen Emitter in seiner Gesamtheit, einschließlich der notwendigen Importanweisungen.

 package import idv.cjcat.stardust.common.actions.Age; idv.cjcat.stardust.common.actions.deathLife importieren; import idv.cjcat.stardust.common.actions.ScaleCurve; import idv.cjcat.stardust.common.clocks.Clock; import idv.cjcat.stardust.common.initializers.Life; idv.cjcat.stardust.common.initializers.Scale importieren; import idv.cjcat.stardust.common.math.UniformRandom; idv.cjcat.stardust.twoD.actions.Damping importieren; import idv.cjcat.stardust.twoD.actions.Move; import idv.cjcat.stardust.twoD.actions.Spin; import idv.cjcat.stardust.twoD.emitters.Emitter2D; import idv.cjcat.stardust.twoD.initializers.DisplayObjectClass; import idv.cjcat.stardust.twoD.initializers.Omega; import idv.cjcat.stardust.twoD.initializers.Position; importieren Sie idv.cjcat.stardust.twoD.initializers.Rotation; import idv.cjcat.stardust.twoD.initializers.Velocity; import idv.cjcat.stardust.twoD.zones.LazySectorZone; import idv.cjcat.stardust.twoD.zones.SinglePoint; public class StarEmitter erweitert Emitter2D / ** * Konstanten * / private static const LIFE_AVG: Number = 30; private statische const LIFE_VAR: Number = 10; private statische Konstante SCALE_AVG: Number = 1; private statische Konstante SCALE_VAR: Number = 0,4; private static const GROWING_TIME: Number = 5; private statische Konstante SHRINKING_TIME: Number = 10; private statische const SPEED_AVG: Number = 10; private statische const SPEED_VAR: Number = 8; private statische Konstante OMEGA_AVG: Number = 0; private statische Konstante OMEGA_VAR: Number = 5; private statische Konstante DÄMPFUNG: Zahl = 0,1; öffentlicher Varpoint: SinglePoint; öffentliche Funktion StarEmitter (Uhr: Uhr) Super (Uhr); Punkt = neuer SinglePoint (); // Initialisierer addInitializer (new DisplayObjectClass (Star)); addInitializer (new Life (neues UniformRandom (LIFE_AVG, LIFE_VAR))); addInitializer (new Scale (neues UniformRandom (SCALE_AVG, SCALE_VAR))); addInitializer (neue Position (Punkt)); addInitializer (neue Geschwindigkeit (neue LazySectorZone (SPEED_AVG, SPEED_VAR)))); addInitializer (neue Rotation (neues UniformRandom (0, 180))); addInitializer (neues Omega (neues UniformRandom (OMEGA_AVG, OMEGA_VAR))); // Aktionen addAction (neues Zeitalter ()); addAction (neues DeathLife ()); addAction (new Move ()); addAction (neuer Spin ()); addAction (neue Dämpfung (DÄMPFUNG)); addAction (new ScaleCurve (GROWING_TIME, SHRINKING_TIME)); 

Schritt 8: Beenden Sie die Dokumentenklasse

Nun ist es Zeit, zur Dokumentenklasse zurückzukehren und sie abzuschließen. Sehen wir uns die verbleibenden Aufgaben an.

  • Erstellen Sie eine StarEmitter-Instanz - Wir werden die gerade abgeschlossene StarEmitter-Klasse instanziieren.
  • Weisen Sie dem Sender ein Uhrobjekt zu - Wir wollen eine konstante Partikelemissionsrate, daher verwenden wir die SteadyClock-Klasse. Der an den Konstruktor der Uhr übergebene Parameter ist die Emissionsrate oder mit anderen Worten die Anzahl der neuen Partikel, die in jedem Emitterschritt erstellt werden. Eine fraktionelle Rate von 0,5 bedeutet in jedem Emitterschritt eine 50% ige Chance, dass ein neues Partikel erzeugt wird, und eine 50% ige Chance, dass kein Partikel erzeugt wird.
  • Erstellen Sie einen Renderer - Um den Partikeleffekt zu visualisieren, benötigen wir einen Renderer. Der DisplayObjectRenderer sollte in Verbindung mit dem DisplayObjectClass-Initialisierer verwendet werden: Der Initialisierer weist jedem Partikel ein Anzeigeobjekt zu. Der Renderer fügt diese Anzeigeobjekte der Anzeigeliste eines Containers hinzu und aktualisiert sie ständig. Vergessen Sie nicht, den Emitter zum Renderer hinzuzufügen.
  • Rufen Sie die Hauptschleife wiederholt auf - Dieser letzte Schritt hält Stardust am Laufen. Hier nutzen wir das Enter-Frame-Event.
  • Nachfolgend finden Sie den vollständigen Code für die Dokumentenklasse, einschließlich der erforderlichen Importanweisungen.

 package import flash.display.Sprite; import flash.display.StageScaleMode; import flash.events.Event; import flash.geom.Rectangle; import idv.cjcat.stardust.common.clocks.SteadyClock; import idv.cjcat.stardust.common.renderers.Renderer; import idv.cjcat.stardust.twoD.renderers.DisplayObjectRenderer; public class StarParticles erweitert Sprite private var emitter: StarEmitter; public function StarParticles () // instanziiert den StarEmitter-Emitter = new StarEmitter (new SteadyClock (0.5)); // der Container sprite var container: Sprite = new Sprite (); // Der Renderer, der den Partikeleffekt rendert. var Renderer: Renderer = new DisplayObjectRenderer (container); renderer.addEmitter (Sender); // füge den Container der Anzeigeliste über dem Hintergrund hinzu addChildAt (container, 1); // das Enter-Frame-Ereignis verwenden addEventListener (Event.ENTER_FRAME, mainLoop);  private Funktion mainLoop (e: Event): void // aktualisiere die SinglePoint-Position auf die Mausposition emitter.point.x = mouseX; emitter.point.y = mouseY; // Aufruf der Hauptschleife emitter.step (); 

Endlich sind wir fertig! Lassen Sie uns nun das Ergebnis betrachten. Drücken Sie in Flash die STRG + EINGABETASTE, um den Film zu testen. Das Ergebnis wird angezeigt.


Variante 1: Animierte Sterne

Wir sind noch nicht fertig! Lassen Sie uns noch ein paar Variationen machen. Der erste verwendet animierte Filmclips für unsere Partikel.

Schritt 9: Erstellen Sie eine Timeline-Animation

Diese erste Variante ist recht einfach und erfordert keine zusätzliche Codierung. Es ist so einfach wie das Erstellen einer einfachen Timeline-Animation. Bearbeiten Sie das Sternsymbol in Flash IDE, erstellen Sie einen anderen Keyframe und ändern Sie die Farbe des Sterns in diesem Frame in Rot. Dies führt im Wesentlichen dazu, dass die Sterne zwischen gelb und rot blinken. Möglicherweise möchten Sie einige leere Bilder dazwischen einfügen, da eine Bildrate von 60 Bildern pro Sekunde für ein Blinken mit zwei Bildern zu schnell ist.

Testen Sie jetzt den Film und überprüfen Sie das Ergebnis. Der blinkende Sterneffekt wirkt cartoonartig; Dies kann für klassische Schwindel-Sterne-Effekte verwendet werden, die häufig in Cartoons zu sehen sind.


Variante 2: Zeitskala dynamisch anpassen

Wie ich bereits erwähnt habe, ist eine der Stardust-Funktionen "einstellbare Simulationszeitskala", dh die von Stardust für die Partikelsimulation verwendete Zeitskala kann dynamisch angepasst werden. Alles wird durch Ändern der Emitter.stepTimeInterval-Eigenschaft vorgenommen, die standardmäßig 1 ist. Das folgende Codefragment ändert diesen Wert in 2, wodurch sich die Partikel doppelt so schnell bewegen und der Emitter neue Partikel mit doppelter Geschwindigkeit erzeugt.

 emitter.stepTimeInterval = 2;

In dieser Variante erstellen wir einen Schieberegler auf der Bühne und verwenden ihn, um die Simulationszeitskala dynamisch anzupassen.

Schritt 10: Erstellen Sie einen Schieberegler

Ziehen Sie eine S