Denken in Befehlen Teil 1 von 2

Zweimal im Monat besuchen wir einige der Lieblingsbeiträge unserer Leser aus der gesamten Geschichte von Activetuts +. Dieses Tutorial wurde erstmals im März 2010 veröffentlicht und ist der erste Teil einer Serie.

Einfacher, wartungsfähiger Code ist schön. Wenn wir jedoch Sequenzen von Aktionen haben, die sich gegenseitig auslösen müssen, kann unser Code unübersichtlich werden, so dass später keine Änderungen mehr möglich sind. Das Befehlsmuster hält die Dinge sauber.

In diesem Tutorial zeige ich Ihnen, wie Sie ein minimalistisches AS3 Command-Framework erstellen, das Aktionen nacheinander, parallel oder verzögert ausführen kann. Sie lernen, wie Sie mit diesem Framework einen komplexen Effekt mit einfachem und sauberem Code erstellen können.


Befehlskapselung

Das Einkapseln von Anweisungen in "Befehle" ist ein beliebter Programmieransatz, um die Dinge zu vereinfachen. Das Befehlsmuster ist eines der am häufigsten verwendeten Entwurfsmuster in der objektorientierten Programmierung. Grundsätzlich wird das Befehlskonzept durch Erstellen von Befehlsklassen implementiert, wobei jede Klasse einen Befehlstyp darstellt. Wenn ich im Rest des Tutorials auf "einen Befehl" beziehe, meine ich "ein Befehlsobjekt"..

Sie können sich einen Befehl als eine Taste auf einer Fernbedienung vorstellen. Jede Taste hat etwas anderes, aber sie werden alle auf dieselbe Weise verwendet: Wenn Sie sie drücken, geschieht die Magie. Wenn Sie den Fernseher einschalten, die Kanäle wechseln oder die Lautstärke einstellen, können Sie diese Funktionen einfach per Tastendruck ausführen.

Mit freundlicher Genehmigung von freedigitalphotos.net

Das Konzept der Befehle ist das gleiche. Die dem Befehl zugrunde liegende Anweisung ähnelt der Funktion einer Fernbedienungstaste. Sie können verschiedene Anweisungen in Befehle einkapseln, z. B. das Herausfinden einer einfachen Nachricht, das Verschieben eines Objekts von einem Ort zum anderen oder das Umschalten der Sichtbarkeit eines Anzeigeobjekts. Sobald die Kapselung abgeschlossen ist, können Sie diese einfach durchführen, indem Sie das Programm dazu auffordern, "die Tasten der Fernbedienung zu drücken" oder mit anderen Worten, "die Befehle auszuführen"..

Wenn Sie möchten, dass das Programm anders arbeitet, können Sie einfach den Code in der Command-Klasse ändern: Das Programm führt immer noch die gleichen Befehle aus, die zuvor ausgeführt wurden, aber der zugrunde liegende Code in den Befehlen ist unterschiedlich. Ihre Gesamtliste der Aktionen, die das Programm ausführen soll, ist getrennt von der detaillierten Liste der Anweisungen, wie die einzelnen Aktionen ausgeführt werden sollen.


Warum sich mit Befehlen beschäftigen?

"Große Sache", könnten Sie sagen, "ich könnte das mit Funktionen tun. Warum sollten Sie Befehle verwenden?" Okay, schauen wir uns zwei Sätze von Code an, die den gleichen Effekt erzeugen, einen mit Funktionen und den anderen mit dem Befehls-Framework, das wir in diesem Lernprogramm erstellen. Der Vorteil von Befehlen wird deutlich.

Nehmen wir an, wir möchten einen Kreis erstellen, ihn zur Bühne hinzufügen, ihn eine halbe Sekunde lang von unsichtbar nach sichtbar machen, zwei Sekunden warten, dann für eine weitere halbe Sekunde wieder unsichtbar machen und ihn dann von der Bühne entfernen. Um dies alles zu tun, verwenden wir die TweenNano-Klasse von Greensock.

Wenn Sie nur Funktionen verwenden, sieht der Code folgendermaßen aus:

 Var Circle: Kreis = neuer Kreis (); addChild (Kreis); TweenNano.from (Kreis, 0.5, alpha: 0, onComplete: func1); function func1 (): void TweenNano.to (Kreis, 0,5, delay: 2, alpha: 0, onComplete: func2);  function func2 (): void removeChild (circle); 

Sehen Sie, wie unsere Liste von Aktionen mit unseren Anweisungen zur Durchführung jeder Aktion verwickelt ist? Um herauszufinden, was passieren wird, müssen Sie allen folgen onCompletes und sehen, wohin sie führen.

Hier ist derselbe Code, der ein Befehls-Framework verwendet:

 Var Circle: Kreis = neuer Kreis (); Befehl var: Befehl = neuer SerialCommand (0, neues AddChild (this, circle), neues TweenNanoFrom (circle, 0.5, alpha: 0), neues TweenNanoTo (circle, 0.5, delay: 2, alpha: 0), new RemoveChild (this, circle)); command.start ();

Hier, AddChild (), TweenNanoFrom, TweenNanoTo, und RemoveChild sind alle Befehlsklassen, die wir an anderer Stelle im Code definieren, und SerialCommand ist eine weitere Befehlsklasse, mit der Sie Befehlssequenzen im Handumdrehen erstellen können.

Ergebnis: keine Funktion mehr "springt". Es ist klar, was diese Sequenz in welcher Reihenfolge tun wird. Es ist auch einfach, die Reihenfolge der Aktionen zu ändern oder eine neue Aktion zwischen den vorhandenen Aktionen einzufügen, ohne den Code für jede Aktion suchen und ihren Code ändern zu müssen onComplete Eigentum.

Mit Befehlen können wir auch verschiedene Aktionen in eine Warteschlange stellen, damit sie gleichzeitig ausgeführt werden - aber dazu kommen wir später!


Die Befehlsklasse

Ein schnelles Beispiel ist mehr als tausend Worte wert. Schauen wir uns also das wesentliche Element unseres Befehls-Frameworks an: die Command-Klasse.

 Paketbefehle import flash.events.Event; import flash.events.EventDispatcher; import flash.events.TimerEvent; import flash.utils.Timer; public class Befehl erweitert EventDispatcher private var _timer: Timer; öffentliche Funktion Befehl (delay: Number = 0) _timer = neuer Timer (int (1000 * delay), 1); _timer.addEventListener (TimerEvent.TIMER_COMPLETE, onTimerComplete);  private Funktion onTimerComplete (e: TimerEvent): void execute ();  / ** * Startet den Befehl. * Wartet auf den Abschluss des Timers und ruft die Methode execute () auf. * Diese Methode kann direkt als Ereignis-Listener verwendet werden. * / public final function start (e: Event = null): void _timer.start ();  / ** * Die abstrakte Methode, die Sie überschreiben müssen, um Ihren eigenen Befehl zu erstellen. * / protected function execute (): void  / ** * Schließt den Befehl ab. * Versendet eine komplette Veranstaltung. * Diese Methode kann direkt als Ereignis-Listener verwendet werden. * / protected final function complete (e: Event = null): void dispatchEvent (neues Ereignis (Event.COMPLETE)); 

Die "emptiest" -Methode ist die execute () -Methode; Diese Methode ist jedoch der wichtigste Teil des Befehls. Um verschiedene Befehlsobjekte erstellen zu können, müssen Sie diese Befehlsklasse erweitern und die Methode execute () überschreiben, indem Sie die Anweisungen eingeben, die Ihr Programm ausführen soll.

Um ein Command-Objekt zum Laufen zu bringen, rufen Sie die start () -Methode auf. Er zählt die Verzögerungszeit mit einem Timer-Objekt herunter und ruft die Methode execute () auf, wenn der Timer den Countdown beendet hat. Eine Verzögerungszeit von Null bedeutet einfach, dass die Methode execute () Ihres Befehlsobjekts direkt nach dem Aufruf der Methode start () aufgerufen wird.

(Beachten Sie, dass Sie nach Abschluss des Befehls die Methode complete () manuell aufrufen müssen, um ein COMPLETE -Ereignis auszulösen. Der Zweck dieser Methode wird später im Lernprogramm deutlich.)

Das Festlegen des Ereignisparameters für die Methoden start () und complete () mit einem Nullwert ist übrigens meine persönliche Gewohnheit. Auf diese Weise können die Methoden wie andere Null-Parameter-Methoden aufgerufen oder direkt als Ereignis-Listener verwendet werden.


Beispiel: Einfache Nachverfolgung

Jetzt, da wir unsere Command-Klasse haben, beginnen wir damit, mit ein paar einfachen Nachverfolgungen zu spielen.


Schritt 1: Erstellen Sie ein Flash-Dokument

Zunächst müssen wir die Flash-IDE öffnen und ein neues Flash-Dokument erstellen. Nennen Sie es SimpleTracing.fla.


Schritt 2: Erstellen Sie die Dokumentenklasse

Erstellen Sie anschließend eine Dokumentenklasse für dieses Flash-Dokument. In diesem Quick Tip finden Sie eine Einführung in Dokumentenklassen.

 package import flash.display.Sprite; public class SimpleTracing erweitert Sprite public-Funktion SimpleTracing () 

Speichern Sie es als SimpleTracing.as.


Schritt 3: Erstellen Sie die Basisbefehlsklasse

Erstellen Sie eine neue AS-Datei und kopieren Sie die Command-Klasse (von oben) hinein.

Erstellen Sie in Ihrem Klassenpfad einen neuen Ordner mit dem Namen "Befehle" und speichern Sie diese neue AS-Datei unter dem Namen Command.as in diesem Ordner.


Schritt 4: Der Trace-Befehl

Zu Beginn möchten wir eine Ablaufverfolgungsfunktion in Befehle einkapseln. Erweitern Sie daher die Command-Klasse, um eine TraceCommand-Klasse für diesen Zweck zu erstellen. Diese Klasse enthält eine Meldungszeichenfolge, die beim Aufruf der Methode execute () nachverfolgt werden soll, und ruft die Methode complete () nach der Ablaufverfolgung auf.

 Paketbefehle public class TraceCommand erweitert Command private var _message: String; public function TraceCommand (delay: Number, message: String) super (delay); _message = Nachricht;  Überschreiben der geschützten Funktion execute (): void trace (_message); Komplett(); 

Speichern Sie dies als TraceCommand.as, ebenfalls im Ordner "command". Sehen Sie, wie wir das überschrieben haben ausführen() Funktion, damit dieser Befehl tatsächlich etwas bewirkt?


Schritt 5: Trace

Ergänzen Sie die Dokumentenklasse mit TraceCommand-Objekten. Fügen Sie Listener für das COMPLETE-Ereignis dieser Befehle hinzu.

 Paket Importbefehle.Befehl; Befehle importieren.TraceCommand; import flash.display.Sprite; import flash.events.Event; public class SimpleTracing erweitert Sprite public function SimpleTracing () var Befehl: Befehl; Befehl = neuer TraceCommand (0, "erster Befehl"); command.addEventListener (Event.COMPLETE, onCommandComplete); command.start (); Befehl = neuer TraceCommand (1, "zweiter Befehl"); command.addEventListener (Event.COMPLETE, onCommandComplete); command.start (); Befehl = neuer TraceCommand (2, "dritter Befehl"); command.addEventListener (Event.COMPLETE, onCommandComplete); command.start ();  private Funktion onCommandComplete (e: Event): void trace ("ein Befehl ist abgeschlossen"); 

Dem Programm mitzuteilen, die Befehle auszuführen, ist so einfach wie das Aufrufen der start () -Methoden der Befehlsobjekte. Testen Sie den Film, und Sie sehen die folgende Ausgabe, die Zeile für Zeile mit einer Zeitspanne von einer Sekunde ausgedruckt wird. Außerdem können Sie die Interlacing-Meldungen sehen, die vom vollständigen Ereignis-Listener der Befehle ausgedruckt werden. Dieselbe Variable wird verwendet, um Verweise auf verschiedene Command-Objekte zu speichern, aber das Programm führt dasselbe mit der Variablen aus: Rufen Sie die start () - Methode auf und warten Sie auf ein COMPLETE-Ereignis.


Zusammengesetzte Befehle

Es gibt Situationen, in denen Sie mehrere Befehle mit komplexem Timing ausführen möchten. Hier werde ich zwei gebräuchliche Arten von Befehlen vorstellen, die ein erweitertes Befehlstiming ausführen können: parallele und serielle Befehle. Beide sind zusammengesetzte Befehle, dh sie enthalten mehrere Unterbefehle. Lass uns sie einzeln überprüfen.


Parallelbefehl

Ein Parallelbefehl führt alle seine Unterbefehle gleichzeitig aus - also parallel. Der Befehl ist nur abgeschlossen, wenn alle Unterbefehle vollständig sind. Die folgende Abbildung zeigt ein visuelles Konzept eines Parallelbefehls. Die schwarzen Pfeilspitzen kennzeichnen den "Fluss" der Befehlsausführung


Die ParallelCommand-Klasse

Nun ist es Zeit, unsere Klasse für parallele Befehle zu erstellen.

Unten ist der vollständige Code für die ParallelCommand-Klasse. Speichern Sie es als ParallelCommand.as in Ihrem "command" -Ordner.

Die Unterbefehle werden als Konstruktor an den Konstruktor übergeben. (Rest) Parameter. Dadurch können wir beliebig viele Befehle an den Konstruktor übergeben. Sie werden automatisch in ein Array namens "Array" eingefügt Befehle. In Kürze werden wir die Schönheit dieser speziellen Parameterart sehen.

 Paketbefehle import flash.events.Event; Die öffentliche Klasse ParallelCommand erweitert Command private var _commands: Array; public function ParallelCommand (delay: Number,? befehle) //? Befehle ist der Parameter "? (Rest)" super (Verzögerung); _Befehle = Befehle;  private var _completeCommandCount: int; letzte geschützte Funktion überschreiben execute (): void // setze die komplette Befehlsanzahl auf Null _completeCommandCount = 0; für jeden (var Befehl: Befehl in _Befehlen) // auf das vollständige Ereignis eines Unterbefehls achten? command.addEventListener (Event.COMPLETE, onSubcommandComplete); //? und starten Sie den Unterbefehl command.start ();  private Funktion onSubcommandComplete (e: Event): void // Stoppt die Überwachung des vollständigen Ereignisses Command (e.target) .removeEventListener (Event.COMPLETE, onSubcommandComplete); // inkrementiere den kompletten Befehl count _completeCommandCount ++; // wenn alle Befehle vollständig sind? if (_completeCommandCount == _commands.length) //? dann ist dieser parallele Befehl abgeschlossen (); 

Diese Klasse überschreibt die Methode execute (). Die neue Methode execute () ruft jetzt die Methode start () aller Unterbefehle auf und wartet auf ihre COMPLETE-Ereignisse. Der COMPLETE-Ereignislistener für die Unterbefehle zählt, wie viele Unterbefehle ausgeführt wurden. Sobald alle Unterbefehle ausgeführt wurden, wird die complete () - Methode von ParallelCommand aufgerufen und löst ein eigenes COMPLETE-Ereignis aus.


Beispiel: Paralleles Tracing

Lassen Sie uns die ParallelCommand-Klasse ausprobieren. Erstellen Sie ein neues Flash-Dokument, kopieren Sie den Ordner "command" in seinen Klassenpfad und schreiben Sie eine neue Dokumentenklasse wie folgt:

 Paket Importbefehle.Befehl; Befehle importieren.ParallelCommand; Befehle importieren.TraceCommand; import flash.display.Sprite; import flash.events.Event; Die public-Klasse ParallelTracing erweitert Sprite public function ParallelTracing () var parallelCommand: Command = new ParallelCommand (0, neuer TraceCommand (0, "1st of 3"), neuer TraceCommand (0, "2nd of 3"), neuer TraceCommand (0 , "Dritter von 3"),); parallelCommand.addEventListener (Event.COMPLETE, onCommandComplete); parallelCommand.start ();  private Funktion onCommandComplete (e: Event): void trace ("alle Befehle sind abgeschlossen"); 

Der Nutzen der Verwendung des Parameters "? (Rest)" für den Konstruktorparameter wird jetzt deutlich. Sie können die Unterbefehle mit dem richtigen Codeeinzug formatieren, um visuell selbsterklärende Codes zu schreiben.

Testen Sie den Film, und Sie sehen die drei Nachrichten gleichzeitig verfolgt und dann eine abschließende Nachricht, die den Abschluss des parallelen Befehls angibt:

  • 1. von 3
  • 2. von 3
  • Dritter von 3
  • Alle Befehle sind abgeschlossen

Wie sieht es mit der Einrichtung von Verzögerungen innerhalb eines Parallelbefehls aus? Einfach. Ändern Sie die Konstruktorfunktion Ihrer Dokumentenklasse wie folgt:

 public function ParallelTracing () var parallelCommand: Befehl = neuer ParallelCommand (0, neuer TraceCommand (0, "erste Welle, 1. von 2"), neuer TraceCommand (0, "erste Welle, 2. von 2"), neuer TraceCommand (1 , "zweite Welle, 1. von 3"), neuer TraceCommand (1, "zweite Welle, 2. von 3"), neuer TraceCommand (1, "zweite Welle, 3. von 3"), neuer TraceCommand (2, "letzte Welle, 1. von 2 "), neuer TraceCommand (2," letzte Welle, 2. von 2 ")); parallelCommand.addEventListener (Event.COMPLETE, onCommandComplete); parallelCommand.start (); 

Testen Sie den Film, und Sie sehen die folgenden drei Wellen von Nachrichten ausgedruckt, mit einer Zeitlücke von einer Sekunde zwischen den einzelnen Wellen:

  • erste Welle, 1. von 2
  • erste Welle, 2. von 2


  • zweite Welle, 1. von 3
  • zweite Welle, 2. von 3
  • zweite Welle, 3. von 3


  • letzte Welle, 1. von 2
  • letzte Welle, 2. von 2

Um eine bessere Vorstellung von den Vorgängen zu erhalten, sehen Sie sich diese Abbildung an:


Serienbefehl

Der zweite zusammengesetzte Befehlstyp ist der serielle Befehl. Ein serieller Befehl führt seine Unterbefehle nacheinander aus, also in Reihe. Zum Beispiel wird der zweite Befehl nach Abschluss des ersten Befehls ausgeführt, und der dritte Befehl wird nach Abschluss des zweiten Befehls ausgeführt. Die folgende Abbildung zeigt ein visuelles Konzept eines seriellen Befehls:


Die SerialCommand-Klasse

Hier ist der Quellcode für die SerialCommand-Klasse. Die überschriebene execute () -Methode ruft die start () -Methode des ersten Unterbefehls auf und wartet auf ihr COMPLETE-Ereignis. Dann startet der Ereignis-Listener den nächsten Unterbefehl und wartet auf sein COMPLETE-Ereignis usw., bis alle Unterbefehle abgeschlossen sind. Zu diesem Zeitpunkt wird das COMPLETE-Ereignis für den gesamten SerialCommand ausgelöst.

 Paketbefehle import flash.events.Event; public class SerialCommand erweitert Command private var _commands: Array; public function SerialCommand (delay: Number,? befehle) super (delay); _Befehle = Befehle;  private var _completeCommandCount: int; letzte geschützte Funktion überschreiben execute (): void // setze die komplette Befehlsanzahl auf Null _completeCommandCount = 0; // auf das vollständige Ereignis des ersten Unterbefehls achten? _Befehle [0] .addEventListener (Event.COMPLETE, onSubcommandComplete); //? und starten Sie den Unterbefehl _commands [0] .start ();  private Funktion onSubcommandComplete (e: Event): void // Stoppen der Überwachung des vollständigen Ereignisses Command (e.target) .removeEventListener (Event.COMPLETE, onSubcommandComplete); // inkrementiere den kompletten Befehl count _completeCommandCount ++; // wenn alle Befehle vollständig sind? if (_completeCommandCount == _commands.length) //? dann ist dieser serielle Befehl abgeschlossen ();  else //? ansonsten auf das vollständige Ereignis des nächsten Unterbefehls achten? _commands [_completeCommandCount] .addEventListener (Event.COMPLETE, onSubcommandComplete); //? und starten Sie den Unterbefehl _commands [_completeCommandCount] .start (); 

Beispiel: Serial Tracing

Verwenden Sie die SerialCommand-Klasse, um eine serielle Ablaufverfolgung durchzuführen. Erstellen Sie wie zuvor ein neues Flash-Dokument, kopieren Sie den Ordner "command" und schreiben Sie eine neue Dokumentenklasse:

 Paket Importbefehle.Befehl; Befehle importieren.SerialCommand; Befehle importieren.TraceCommand; import flash.display.Sprite; import flash.events.Event; public class SerialTracing erweitert Sprite öffentliche Funktion SerialTracing () var serialCommand: Befehl = neuer SerialCommand (0, neuer TraceCommand (0, "erster Befehl"), neuer TraceCommand (1, "zweiter Befehl"), neuer TraceCommand (1, " dritter Befehl ")); serialCommand.addEventListener (Event.COMPLETE, onCommandComplete); serialCommand.start ();  private Funktion onCommandComplete (e: Event): void trace ("alle Befehle sind abgeschlossen"); 

Testen Sie den Film, und die folgenden Meldungen werden nacheinander mit einer Zeitlücke von einer Sekunde verfolgt, gefolgt von "Alle Befehle sind abgeschlossen"..

  • erster Befehl


  • zweiter Befehl


  • dritter Befehl

Hier ist eine Konzeptfigur dieses Beispiels, die Ihnen hilft, die Vorgänge besser zu verstehen.


Verschachtelte zusammengesetzte Befehle

Bis jetzt haben wir nur die grundlegendste Verwendung von parallelen und seriellen Befehlen untersucht, und es scheint keinen Grund zu geben, sie anstelle von separaten Befehlen zu verwenden. Es gibt jedoch Zeiten, in denen Sie viel komplexere Befehlsausführungen benötigen, und Sie können mehrere zusammengesetzte Befehle kombinieren, um verschachtelte Befehle zu erstellen, die Ihren Anforderungen entsprechen. Im nächsten Beispiel wird veranschaulicht, wie Sie mit der ParallelCommand-Klasse und der SerialCommand-Klasse solche verschachtelten Befehle erstellen.


Beispiel: Verschachtelte Befehle

Erstellen Sie wie zuvor ein neues Flash-Dokument, kopieren Sie den Ordner "command" und schreiben Sie eine neue Dokumentenklasse:

 Paket Importbefehle.Befehl; Befehle importieren.ParallelCommand; Befehle importieren.SerialCommand; Befehle importieren.TraceCommand; import flash.display.Sprite; import flash.events.Event; public class NestedCommands erweitert Sprite public function NestedCommands () var nestedCommands: Befehl = neuer SerialCommand (0, neuer ParallelCommand (0, neuer TraceCommand (0, "Parallelbefehl # 1, Teil 1 von 2"), neuer TraceCommand (0, "Parallelbefehl # 1, Teil 2 von 2"), neuer TraceCommand (0, "------------------------------- - ")), neuer ParallelCommand (1, neuer TraceCommand (0," Parallelbefehl # 2, Teil 1 von 3 "), Neuer TraceCommand (0," Parallelbefehl # 2, Teil 2 von 3 "), Neuer TraceCommand (0 , "Parallelbefehl # 2, Teil 3 von 3"), neuer TraceCommand (0, "------------------------------ - ")), neuer ParallelCommand (1, neuer TraceCommand (0," letzter Befehl "), neuer TraceCommand (0," ---------------------- ---------- "))); nestedCommands.addEventListener (Event.COMPLETE, onCommandComplete); nestedCommands.start ();  private Funktion onCommandComplete (e: Event): void trace ("alle Befehle sind abgeschlossen"); 

Testen Sie den Film, und das Programm druckt die folgenden Meldungsblöcke nacheinander mit einer Zeitlücke von einer Sekunde aus. Wie in den vorherigen Beispielen wird eine endgültige vollständige Nachricht ausgedruckt, wenn alle Unterbefehle abgeschlossen sind.

  • Parallelbefehl # 1, Teil 1 von 2
  • Parallelbefehl # 1, Teil 2 von 2
  • --------------------------------


  • Parallelbefehl # 2, Teil 1 von 3
  • Parallelbefehl # 2, Teil 2 von 3
  • Parallelbefehl # 2, Teil 3 von 3
  • --------------------------------


  • letzter Befehl
  • --------------------------------

Hier ist die Konzeptfigur dieses Beispiels.


Beispiel: Lichtstromkreis

Abschließend betrachten wir ein praktischeres Beispiel. Wir werden das von uns entwickelte Befehls-Framework verwenden, um eine Demo für leichte Schaltungen mit fortgeschrittenem Timing zu erstellen. Bevor Sie beginnen (Sie haben es erraten), erstellen Sie ein neues Flash-Dokument, kopieren Sie den Ordner "command" und erstellen Sie eine neue Dokumentenklasse.


Schritt 1: Das Lichtsymbol

Erstellen Sie ein Movieclip-Symbol mit einer Timeline-Animation, bei der ein Kreis seine Farbe von grau nach gelb ändert.

Fügen Sie in der Zeitleiste am letzten Keyframe den folgenden Code hinzu. Dadurch wird die Animation des Movieclips angehalten und ein COMPLETE-Ereignis ausgelöst.

 halt(); dispatchEvent (neues Ereignis (Event.COMPLETE));

Wenn Sie die Codierung auf der Timeline vermeiden möchten, können Sie eine Klasse für Ihren Light MovieClip mit einer Funktion erstellen:

 public function reachEndOfAnimation (): void stop (); dispatchEvent (neues Ereignis (Event.COMPLETE)); 

? Schreiben Sie dann im Konstruktor für diese Klasse Folgendes:

 addFrameScript (4, reachEndOfAnimation) //, wobei 4 um 1 kleiner ist als die Anzahl der Frames

Schritt 2: Die Schaltung

Ordnen Sie die Lichtinstanzen auf der Bühne an und benennen Sie sie wie in der folgenden Abbildung dargestellt:


Schritt 3: Interaktion

Ziehen Sie eine Button-Komponente aus dem Komponentenbereich auf die Bühne und nennen Sie sie "start_btn". Wir möchten unsere Befehle ausführen, wenn diese Taste gedrückt wird.


Schritt 4: Abschlussindikator

Erstellen Sie auf der Bühne ein Textfeld und geben Sie Ihre Abschlussnachricht ein. Konvertieren Sie es anschließend in ein Movieclip-Symbol und benennen Sie die Instanz "completeMessage_mc"..


Schritt 5: Die Dokumentenklasse

Nun ist es Zeit, die Dokumentenklasse zu bearbeiten. Deklarieren Sie eine private Variable "circuitCommand", die zum Speichern einer Referenz auf ein Command-Objekt verwendet wird:

 private var circuitCommand: Befehl;

Zu Beginn des Programms müssen alle Lichter ausgeschaltet sein, d. H. Beim ersten Frame angehalten werden, und die Abschlussmeldung sollte ausgeblendet sein. Also rufen wir die reset () -Methode im Konstruktor auf.

 reset ();

Erstellen Sie dann unsere verschachtelten Befehle, die die Animationen der Light Movie Clips abspielen und sie mit dem richtigen Timing beleuchten. Wir verwenden hier eine PlayCommand-Klasse, die einfach die play () -Methode eines Movieclips aufruft. Wir werden die Klasse später schreiben.

 circuitCommand = neuer SerialCommand (0.5, neuer PlayCommand (0, light_1), neuer ParallelCommand (0.5, neuer PlayCommand (0, light_2_1), neuer PlayCommand (0, light_2_2)), neuer PlayCommand (0.5, light_3), neuer ParallelCommand (0.5, neuer PlayCommand (0, light_4_1), neuer PlayCommand (0, light_4_2)), neuer PlayCommand (0.5, light_5));

Hören Sie als Nächstes auf das COMPLETE-Ereignis des Befehls und das CLICK-Ereignis der Starttaste:

 circuitCommand.addEventListener (Event.COMPLETE, onCommandComplete); start_btn.addEventListener (MouseEvent.CLICK, startCircuit);

Schritt 6: Hinzufügen von Ereignishandlern

Zeigt die Abschlussmeldung an, wenn der Befehl abgeschlossen ist:

 private Funktion onCommandComplete (e: Event): void completeMessage_mc.visible = true; 

Setzen Sie die Schaltung zurück und starten Sie den Befehl, wenn Sie auf die Schaltfläche Start klicken.

 private Funktion startCircuit (e: MouseEvent): void reset (); circuitCommand.start (); 

Schritt 7: Die Rücksetzmethode

Der letzte Teil für die Dokumentenklasse ist die reset () -Methode. Mit Befehlen hier nichts zu tun.

 private Funktion reset (): void completeMessage_mc.visible = false; light_1.gotoAndStop (1); light_2_1.gotoAndStop (1); light_2_2.gotoAndStop (1); light_3.gotoAndStop (1); light_4_1.gotoAndStop (1); light_4_2.gotoAndStop (1); light_5.gotoAndStop (1); 

Schritt 8: Die PlayCommand-Klasse

Der letzte Teil dieses Beispiels ist die PlayCommand-Klasse. Wie bereits erwähnt, können Sie einfach die play () -Methode eines Movieclips aufrufen. Sobald die play () -Methode in der überschriebenen ausführten () -Methode des Befehls aufgerufen wird, wird auch die complete () -Methode aufgerufen.

 Paketbefehle import flash.display.MovieClip; import flash.events.Event; public class PlayCommand erweitert Command private var _movieClip: MovieClip; öffentliche Funktion PlayCommand (delay: Number, movieClip: MovieClip) super (delay); _movieClip = movieClip;  Überschreibe die geschützte Funktion execute (): void _movieClip.addEventListener (Event.COMPLETE, complete); _movieClip.play (); 

Speichern Sie dies als PlayCommand.as in Ihrem "Befehls" -Ordner.


Schritt 9: Testen Sie den Film

Alles klar, wir sind fertig! Testen Sie jetzt den Film und Sie sehen, dass die Lichter von links nach rechts leuchten, nachdem Sie auf die Start-Schaltfläche geklickt haben. Die Abschlussmeldung wird angezeigt, wenn alle Leuchten leuchten.

Hier ist die visuelle Darstellung der Vorgänge in diesem Beispiel:

Vergleichen Sie es mit dem eigentlichen Code und sehen Sie, wie einfach es zu verstehen ist:

 neuer SerialCommand (0.5, neuer PlayCommand (0, light_1), neuer ParallelCommand (0.5, neuer PlayCommand (0, light_2_1), neuer PlayCommand (0, light_2_2)), neuer PlayCommand (0.5, light_3), neuer ParallelCommand (0, light_4_1), neuer PlayCommand (0, light_4_2)), neuer PlayCommand (0.5, light_5));

Mit der richtigen Codeeinrückung kann ein komplexer verschachtelter Befehl als einfacher und sauberer Code ausgedrückt werden.


Zusammenfassung

In diesem Lernprogramm haben Sie das Konzept der Befehle kennen gelernt. Anweisungen können in Befehle gekapselt werden, die über identische Schnittstellen verfügen, so wie jede Taste einer Fernbedienung eine andere Aktion hat. Die Methode zum Aufrufen jeder Aktion ist jedoch dieselbe: Drücken Sie die Taste.

In diesem Lernprogramm wurden außerdem zwei Arten von zusammengesetzten Befehlen vorgestellt: parallel und seriell. Diese können verwendet werden, um verschachtelte Befehle zu erstellen, die eine erweiterte Befehlsausführungszeit ermöglichen, während der Code sauber bleibt.


Fazit

Das Konzept der Befehle ist sehr bequem und leistungsstark. Code Encapsulation ist die Hauptmethode, um die Programmierung zu vereinfachen. Eine der am häufigsten verwendeten Methoden ist die Verwendung von Befehlsobjekten. Ich hoffe, dieses Tutorial hilft Ihnen, die Verwendung von Befehlen in praktischen Anwendungen besser zu verstehen.

Im nächsten Teil dieses Tutorials zeige ich Ihnen, wie Sie TweenLite in das von uns erstellte Befehls-Framework integrieren und Szenenübergänge mit einfachem und sauberem Code behandeln. Vielen Dank fürs Lesen.