Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. ActionScript
Code

Die Macht der Endlichen Zustandsmaschinen (FSM): Konzept und Erstellung

by
Difficulty:IntermediateLength:LongLanguages:

German (Deutsch) translation by Katharina Nevolina (you can also view the original English article)

Dieses zweiteilige Tutorial behandelt die Erstellung eines mehrstufigen Autos mit einer endlichen Zustandmaschine.  Wir werden mit Procedural FSM beginnen und in das Designmuster State Pattern übergehen.  Konzept und Erstellung stehen bei diesem ersten Teil im Vordergrund. Wir werden dann im zweiten Teil in Anwendung und Erweiterung gehen.


Finale Ergebnisvorschau

Werfen wir einen Blick auf das Endergebnis, auf das wir hinarbeiten werden:


Was ist eine endliche Zustandsmaschine?

Wikipedia definiert eine FSM (Finite State Machine) als eine mathematische Abstraktion, die manchmal verwendet wird, um digitale Logik oder Computerprogramme zu entwerfen.  Es ist ein Verhaltensmodell, das aus einer endlichen Anzahl von Zuständen, Übergängen zwischen diesen Zuständen und Aktionen besteht, ähnlich einem Flussgraphen, in dem man untersuchen kann, wie die Logik abläuft, wenn bestimmte Bedingungen erfüllt sind.

Es hat endliches internes Gedächtnis; ein Eingabemerkmal, das Symbole nacheinander in einer Sequenz liest, ohne rückwärts zu gehen; und ein Ausgabefeature, das in der Form einer Benutzerschnittstelle sein kann, sobald das Modell implementiert ist.  Die Operation einer FSM beginnt von einem der Zustände (als Startzustand bezeichnet), geht durch Übergänge (abhängig von den Eingaben) in verschiedene Zustände und kann in jedem der verfügbaren Zustände enden - jedoch markiert nur ein bestimmter Satz von Zuständen a erfolgreicher Ablauf der Operation.

In meinen eigenen Worten ist ein FSM ein Gerät, das von Entwicklern verwendet wird, um Objekte zu erstellen, die unterschiedliche Verhaltensweisen haben, die durch den aktuellen Zustand bestimmt werden.  Abhängig von der Eingabe kann das Objekt reagieren und/oder in einen anderen Zustand übergehen.

Ein gutes Beispiel wäre eine 1970 HK VP70Z-Maschinenpistole, die drei Schussmodi hat: Sicherheit, Einzelschuss und halbautomatischer Drei-Runden-Stoß.  Abhängig vom aktuellen Modus, den Sie auf (Zustand) eingestellt haben, ist das Ergebnis (Ausgang) unterschiedlich, wenn Sie den Auslöser (Eingang) ziehen.

Werkzeuge: Wenn Sie eine Idee konzeptionieren (das Objekt mit mehreren Zuständen, das Sie erstellen möchten), empfiehlt es sich, eine Zustandsübergangstabelle zu verwenden, um zu erfahren, welche Zustände und Aktionen für diese Zustände hinzugefügt werden müssen.


Schritt 1: Installation

Es ist Zeit, ein neues Projekt zu beginnen.  Erstellen Sie mit FlashDevelop ein neues AS3-Projekt.  Für den Namen, setzen Sie CarFSM.  Klicken Sie auf "Durchsuchen ..." und speichern Sie sie an Ihrem gewünschten Ort.  Gehen Sie in den Paket-Slot und geben Sie "com.activeTuts.fsm" ein.  Stellen Sie sicher, dass das Kontrollkästchen "Verzeichnis für Projekt erstellen" ausgewählt ist, und klicken Sie zum Abschluss auf "OK".

description of image

Sobald das Projekt in FlashDevelop geladen wurde, klicken Sie auf "Ansicht" und wählen Sie "Projektmanager".  Sehen Sie den Ordner "src"?  Klicken Sie mit der rechten Maustaste darauf und wählen Sie "Durchsuchen".

description of image

Wenn Sie diesen Ordner geöffnet haben, sollten Sie den Ordner "com" sehen, den Sie zuvor erstellt haben.  Öffnen Sie den Quellcode, den ich in diesem Tutorial eingefügt habe, und ziehen Sie den Ordner "assets" in "src"; vergewissern Sie sich, dass Sie es nicht in den Ordner "com" legen.

Als nächstes gehen Sie in den Quellcode "com" Ordner und ziehen Sie den "bit101" Ordner in den "com" Ordner in "src".  Sie können auch minimalComps hier herunterladen, wenn Sie es direkt von der Quelle beziehen möchten.

Schließlich, reißenSie innerhalb der "com" Ordner (innerhalb "src") bis hin zu "fsm" auf und doppelklicken Sie auf Main.as.  Das sollte jetzt in FlashDevelop geöffnet sein (vorausgesetzt, Sie haben FD als Standardanwendung für die Erweiterung).


Schritt 2: Aufwärmen

Wir beginnen mit der Betrachtung der beiden Zustände eines noch einfacheren Beispiels: das Kontrollkästchen von MinimalComps.

Nehmen wir an, wir möchten ein Kontrollkästchen, die ihren aktuellen Status widerspiegelt, indem sie ihre Bezeichnung ändert.  Unten ist die Übergangstabelle für das Kontrollkästchen.

description of image

Jetzt für den Code.  Fügen Sie in Main.as, eine Zeile unterhalb der Klassenimporte, die unten gezeigten Metadaten hinzu.

Als nächstes gehen Sie innerhalb der init()-Methode und setzen Sie den Cursor unter dem Punkt "Einstiegspunkt".  Fügen Sie dann einen Methodenaufruf simpleExample() hinzu.  Stellen Sie als Nächstes sicher, dass der Cursor innerhalb des Methodenaufrufs aktiv ist, und drücken Sie die Tastenkombination "CTRL + SHIFT + 1".  Eine Eingabeaufforderung wird angezeigt. Wählen Sie "Private Funktion generieren" und drücken Sie die Eingabetaste.

description of image

Kopieren Sie nun den folgenden Code und fügen Sie ihn in die neu erstellte Methode ein.  Als nächstes setzen Sie Ihren Cursor in das Wort "CheckBox" und drücken Sie "CTRL + SHIFT + 1", um automatisch die gewünschte Klasse zu importieren.  Sobald Sie fertig sind, drücken Sie "CTRL + ENTER", um die Anwendung auszuführen.

Wenn Sie Fehler feststellen, vergleichen Sie bitte Ihre Klassen mit denen, die ich mit dem Quelle-Herunterladen hinzugefügt habe.

Sie sollten etwas haben, das dem ähnelt, was Sie über dieser Linie sehen.  Es gibt Ihre zwei Zustände, ON und OFF.  Jedes Mal, wenn Sie klicken, schaltet das Kontrollkästchen Zustände um und ändert auch seine Beschriftung als Ausgabeform.

Auf zum echten "Auto" FSM-Projekt.  Stellen Sie sicher, dass das Projekt im Modus "Debug" ausgeführt wird, um trace()-Anweisungen zu aktivieren.


Schritt 3: Die prozedurale Auto-FSM

Okay, vergessen wir die Vorschau oben auf der Seite und starten die Auto-FSM von Grund auf neu.  Heben Sie in Main.as die init()-Methode zusammen mit der simpleExample()-Methode hervor und drücken Sie die Taste "BACK", um sie zu entfernen.

Gehen Sie eine Zeile über den Konstruktor und fügen Sie die folgenden Variablen hinzu.

Die Variablen _past, _present, _tick und _counter werden alle für die zeitgesteuerte Ausführung verwendet. Ich werde bald mehr darüber erklären.  Die _car-Variable enthält einen Verweis für die Car-Klasse, die die prozeduralen Car FSM-Aktionen einkapselt.  Der Rest sind Boolesche Eigenschaften, die zum Auslösen von zeitgesteuerten Aktionen verwendet werden.

Arbeiten wir an der zeitgesteuerten Ausführung.  Fügen Sie den folgenden Code in den Konstruktor ein.

Bewegen Sie den Cursor in das Wort "update" und drücken Sie "CTRL + SHIFT + 1" und wählen Sie "Event-Handler generieren". de. Wenn Sie die Anwendung testen, sehen Sie einen Ausdruck ähnlich "Start des Konstruktors = 2.119 Sekunden" (es könnte weniger sein, wenn Sie einen schnelleren PC haben).  Es entspricht dem Teilen von getTimer() mit 1000, aber die Multiplikation ist schneller.

Gehen wir zur update()-Methode.  Fügen Sie den folgenden Code hinzu.

Wenn Sie es jetzt erneut testen, werden Sie alle zwei Sekunden eine trace()-Anweisung sehen.  Der _counter wird dann auf die Überlappung zurückgesetzt, die er hatte, um die Zeitgenauigkeit einzuhalten.

Versuchen Sie es mit einem anderen Wert als zwei Sekunden und führen Sie es ein paar Mal aus.

Zur Car-Klasse.  Bevor Sie fortfahren, gehen Sie voran und entfernen Sie die if()-Anweisung in der update()-Methode.


Schritt 4: Die Car-Klasse

Wie ich bereits erwähnt habe, beginnen wir mit einer neuen Idee, ein mehrstufiges Auto zu schaffen.  Nehmen wir an, wir haben beschlossen, ein Auto zu haben, das ein- und ausgeschaltet werden kann, auch vorwärts gefahren werden kann und kein Benzin mehr hat.  Das würde uns vier verschiedene Zustände geben - ON, OFF, DRIVE_FORWARD und OUT_OF_FUEL.

Das erste, was zu tun ist, ist, die verschiedenen Zustände und Handlungen für diese Staaten in einer Zustandsübergangs-Tabelle auszuarbeiten.  Sie können einen Stift und ein leeres Blatt Papier verwenden, um alle Zustände und Aktionen, die das Auto-Objekt benötigen würde, schnell zu notieren.  Sehen Sie das Bild unten.

description of image

Verwenden Sie immer eine "update()" -Methode, um Ihre Bundesstaaten in Echtzeit zu steuern.  Wie verbrauchen Sie eine höhere Menge an Kraftstoff beim Fahren als bei Leerlauf im Park.

Es ist einfach zu sagen, wie jeder Staat auf jede der Aktionen reagieren sollte.  Es erscheint einfach, weil wir (Menschen) alle denken, dass Objekte in dem einen oder anderen Zustand sind.

Jetzt können wir die Klasse programmieren.

Wechseln Sie in der Konstruktormethode in Main.as eine Zeile vor dem Ereignisereignis ENTER_FRAME und fügen Sie den folgenden Code hinzu.

Jetzt, da es keine Car-Klasse gibt, bewegen Sie den Cursor in das Wort "Car" und drücken Sie "CTRL + SHIFT + 1", wählen Sie "Erstellen Sie eine neue Klasse" und drücken Sie die "ENTER"-Taste.

Verwenden Sie dieselben Informationen wie unten gezeigt.  Klicken Sie auf "OK", um zu beenden.

description of image

Sie sollten jetzt die Car-Klasse in FlashDevelop geöffnet haben.


Schritt 5: Car-Variablen

Fügen Sie den Code unterhalb einer Zeile über dem Klassenkonstruktor hinzu.

Das Auto ist so eingestellt, dass es nur 6 Mal pro Sekunde Kraftstoff verbraucht.  Das wird durch die Klassenkonstante ONE_SIXTH_SECONDS repräsentiert.  Außerdem hängt die Verbrauchsmenge davon ab, ob das Auto im Leerlauf ist oder vorwärts fährt.  Wir verwenden IDLE_FUEL_CONSUMPTION und DRIVE_FUEL_CONSUMPTION für diese Zwecke.

Die vier Zustände werden durch String-Konstanten repräsentiert, wobei ENGINE_OFF als Standard gesetzt ist.

Die Eigenschaft _engineTimer wird verwendet, um consumeFuel() alle 1/6 Sekunden auszulösen, jedoch nur, wenn der Status ENGINE_ON oder ENGINE_DRIVE_FORWARD lautet.

Schließlich nimmt _fuelSupply (was consumeFuel() langsam wegnimmt) den Wert von _fuelCapacity für einen vollen Tank ein.


Schritt 6: Methoden aus der Zustandsübergangstabelle

Lassen Sie den Car-Konstruktor für jetzt leer.  Gehen Sie darunter und fügen Sie die unten gezeigte update()-Methode hinzu.

Wir rufen Main.as diese Methode bei jedem ENTER_FRAME-Ereignis auf, das die verstrichene Zeit zwischen Frames verstreichen lässt.  Einmal aufgerufen, überprüft es den aktuellen Zustand des Autos und führt die entsprechende Aktion aus.

Wenn dieser Status nicht überschritten wird, kann der Statusübergang nur über consumeFuel() erfolgen, wodurch der Wert auf OUT_OF_FUEL gesetzt wird, wenn _fuelSupply abgelaufen ist.

Hinweis: Aktionen, die sich in Ihrer Zustandsübergangstabelle befinden, sind immer öffentlicher Zugriff, der als Eingabesteuerelemente verwendet wird.  Das gilt unabhängig davon, ob Sie Procedural FSM oder das State Pattern verwenden.


Schritt 7: Einschalten des Autos

Fügen Sie den folgenden Code nach der update()-Methode hinzu.

Genau wie die update()-Methode wird _currentState überprüft und die entsprechende Aktion ausgeführt.  Es erklärt sich ziemlich genau.


Schritt 8: Das Auto ausschalten.

Das gleiche gilt für das Ausschalten des Autos.  Fügen Sie es als nächstes hinzu.

Es wird sehr einfach, die Methoden zu erstellen.  Kopieren Sie einfach die vorherige, fügen Sie sie ein und nehmen Sie dann ein paar Änderungen vor.


Schritt 9: Vorwärts fahren

Gehen Sie immer zu Ihrer Zustandsübergangstabelle zurück, um zu sehen, was für jeden Zustand geschehen muss, wenn Sie die Eingabemethode aufrufen, an der Sie gerade arbeiten.

Fügen Sie den Code unterhalb der TurnKeyOff()-Methode hinzu.


Schritt 10: Fuel verbrauchen

Diese Methode ist privat, da nur das Auto darauf zugreifen muss.  Es ruft sechs Mal pro Sekunde von update().

Setzen Sie den Code nach der Methode driveForward().

Jetzt sehen Sie, wie der Code geht, wie zuvor im Abschnitt Klassenvariablen erklärt.


Schritt 11: Tanken Sie das Auto

Diese Methode ist privat, da nur das Auto darauf zugreifen muss.

Setzen Sie den Code als nächstes.

Die Methode prüft zuerst, ob das Auto einen vollen Tank hat.  Wenn ja, sagt es Ihnen, dass es einen vollen Tank hat und verlässt die Methode.

Wenn das Auto andererseits keinen vollen Tank hat, durchläuft es die bekannte case/switch-Anweisung und führt die richtige trace()-Anweisung aus.

Das letzte Bit des Codes berechnet die Menge an verbrauchtem Kraftstoff und füllt nur diesen auf, um einen vollen Tank zu behalten.  Es druckt dann den Wert eines vollen Tanks.


Schritt 12: Verwenden von toString(), um trace() Anweisungen zu unterstützen

Diese Methode musste außer Kraft gesetzt werden, da das Car von Sprite erbt, das wiederum von EventDispatcher erbt.

Es gibt nur eine String-Anweisung zurück, die unten angezeigt wird.  Fügen Sie es als letzte Methode für die Klasse Auto hinzu.

So, jetzt, wenn Sie rufen trace(_car) von Main.as, anstelle von "[object Car]" erhalten Sie eine Aussage wie "Das Auto ist derzeit aus mit einer Kraftstoffmenge von 1,00 Gallonen (s)."

Lassen Sie uns zum Testen zu Main.as zurückkehren.  Speichern Sie Ihre Arbeit, bevor Sie fortfahren.


Schritt 13: Belastungstest

Innerhalb des Konstruktors von Main, direkt nach dem Sie den Ereignis-Listener ENTER_FRAME hinzugefügt haben.  Geben sie den untenstehenden Code ein.

An diesem Punkt wird das Auto alle sechs Aktionen ohne Zeitverlust ausführen.  Das Ereignis ENTER_FRAME wurde noch nicht gestartet.

Als nächstes gehen Sie in die update()-Methode direkt unterhalb von wo _tick zu _counter hinzugefügt wird und fügen Sie den Code ein, der als nächstes angezeigt wird.

Ich weiß, es ist viel Code, aber es ist selbsterklärend.  Führen Sie die Anwendung aus und überprüfen Sie Ihre Ausgabe.

Wenn Sie Fehler erhalten, vergewissern Sie sich, dass Sie Ihren Code mit den Klassen vergleichen, die in diesem Lernprogramm enthalten sind.

Versuchen Sie, _fuelCapacity in Car zu ändern und verwechseln Sie die Methoden in einigen oder allen Testabschnitten und führen Sie sie erneut aus.  Sie werden feststellen, dass der Code solide ist und diese prozedurale FSM wirksam ist.  Und das ist es!  Wir sind fertig.

Warten Sie eine Minute.  Da alles gut ist, warum fügen wir nicht die Fähigkeit hinzu, rückwärts und turbo zu fahren?  Währenddessen können wir auch Animation und Sound hinzufügen.  Stellen Sie sich nun vor, wie aufgebläht die Auto-Klasse wird, wenn Sie dafür sorgen, dass all die Dinge erledigt werden, die das Auto oben auf der Seite macht.  Wir schauen uns vielleicht 2000 Zeilen Code an - zumindest.  LOL! Ich würde wahrscheinlich sagen: Ja, klar, ich kann das hacken.  Aber der Code wird sehr zerbrechlich und leicht zu knacken.  Es könnte also eine gute Idee sein, eine andere Technik zu verwenden.

Wenn das FSM-Objekt ein einfaches Verhalten aufweist, verwenden Sie diese Technik auf jeden Fall.  Wenn Sie jedoch ein komplexes Objekt haben, das in Zukunft möglicherweise neue Funktionen hinzufügen muss.  Vielleicht fügen Sie noch ein paar weitere Zustände hinzu - nun, hier kommt das State Pattern ins Spiel.


Schritt 14: Einführung des Zustandsmusters

Begrüßen Sie den "großen Bruder" von Procedural FSM.  Durch die Verwendung dieses Entwurfsmusters können Sie Ihre Status einfach verwalten und ändern, aber der beste Teil - andere Status können jetzt hinzugefügt werden, ohne dass der Code ruiniert werden muss.

Um dieses Muster anzuwenden, verweisen wir erneut auf unsere vertrauenswürdige Zustandsübergangstabelle.  Sehen Sie Schritt 4. Das Zustandsmuster besteht aus drei Teilen.  Das erste ist die Zustandsschnittstelle, diese enthält alle Aktionen, die Sie in der Zustandsübergangstabelle sehen.  Darüber hinaus kann diese Zustandsschnittstelle auch Methoden enthalten, die von allen State-Klassen gemeinsam genutzt werden.  Zweitens, die State-Klassen, die für jeden in Ihrer Zustand-Transition-Tabelle gezeigten Staat entsprechen.  Und drittens die Zustandsmachine - das ist normalerweise dein umgewandeltes Procedural FSM-Objekt (die Car-Klasse).  Nach der Konvertierung stellt das Auto öffentliche Accessoren und Modifikatoren zur Verfügung, um externe Kontrolle von allen staatlichen Klassen zu ermöglichen.  Das Auto wird Aktionen an den derzeit aktiven Zustand delegieren.


Schritt 15: Beginn der Konvertierung

Klicken Sie auf "Ansicht" und wählen Sie "Projektmanager".  Machen Sie in "src" einen Drilldown, bis Sie den Ordner "fsm" sehen.  Klicken Sie mit der rechten Maustaste darauf und wählen Sie "Hinzufügen > Neue Schnittstelle ...(Add > New Interface)" und drücken Sie "ENTER".

description of image

Nennen Sie es "IState".  Schnittstellen beginnen mit "I" für die Namenskonvention.

Sobald FlashDevelop die Klasse öffnet, fügen Sie den folgenden Code hinzu.

Diese IState-Schnittstelle wird von allen State-Klassen implementiert.  Die letzte Funktion toString() hat nichts mit der Kontrolle des Autos zu tun, aber alle Staatsklassen benutzen es.

Weitere Informationen zu Interfaces finden Sie unter AS3 101: Einführung in Interfaces.  Beginnen wir mit dem Hinzufügen der Zustandsklassen.


Schritt 16: Die EngineOff-Klasse

Folgen Sie dem gleichen Verfahren, wenn Sie die IState-Schnittstelle erstellt haben, wählen Sie aber stattdessen "Neue Klasse hinzufügen".

description of image

Nennen Sie es "EngineOff".  Klicken Sie für den Schnittstellensteckplatz auf Hinzufügen, und geben Sie "IState" ein. Das sollte die IState-Klasse innerhalb desselben Ordners finden.  Außerdem sollte das Kontrollkästchen für "Implementierungen der Schnittstellenmethoden generieren" ausgewählt sein.  Klicken Sie zum Abschluss auf "OK".

Die neue Klasse kommt halbwegs fertig.  Es sollte dem, was unten angezeigt wird, sehr ähnlich sein.

Diese Statusklassen müssen Sprite nicht erweitern, da alle Media-Assets (zweiter Teil) hinzugefügt und über das Auto gesteuert werden.  Die Zustände werden instanziiert, indem sich die Car-Klasse selbst als Referenz definiert.  Eine Zweiwege-Kompositionsstruktur wird verwendet, um die Kommunikation zwischen dem Auto und den staatlichen Klassen zu ermöglichen.


Schritt 17: Beenden unserer EngineOff-Klasse

Ändern Sie die Konstruktormethode so, dass sie dem folgenden Code entspricht.

Ich habe die Variable _car über den modifizierten Konstruktor eingefügt.  Jetzt können wir die Car-Klasse von diesem Zustand aus kontrollieren.

Gehen wir zu den Implementierungen der Schnittstellenmethode über.

Rufen Sie die Methode turnKeyOff() auf.  Überprüfen Sie Ihre Zustandsübergangstabelle, um zu sehen, was hier passiert.  Als nächstes vergleichen Sie das mit der prozeduralen turnKeyOff() Methode innerhalb der Car-Klasse.  Denken Sie daran, dass wir noch die Car-Klasse in Procedural FSM haben.  Sobald Sie das Spiel sehen.  Kopieren Sie die Aktion für den Status ENGINE_OFF in die leere Methode.  Die turnKeyOff()-Methode sollte das widerspiegeln, was Sie unten sehen.

Die Anweisung trace() wurde durch print() ersetzt, die wir später zur Klasse Car hinzufügen.

Gehen Sie nun in die Methode turnKeyOn() und fügen Sie den folgenden Code hinzu.

Überprüfen Sie es gegen Sie Zustandsübergangstabelle und prozedurale turnKeyOn()-Methode für den ENGINE_OFF-Zustand, um zu sehen, ob es gleich ist.  Die changeState()-Methode wird an das Fahrzeug delegiert, das im abgerufenen Status übergeben wird.

Der Rest der Methoden wird auf die gleiche Weise verarbeitet.  Kopieren Sie den folgenden Code und ersetzen Sie die leeren Methoden damit.

Die driveForward()-Methode funktioniert genauso wie die procedure driveForward() -Methoden, wobei _currentState als ENGINE_OFF festgelegt ist

reFuel() fragt das Auto, ob der Tank nicht voll ist.  Wenn nicht, wird das Auto dann mit Kraftstoff nachfüllen.  Sie werden sehen, wie diese beiden Methoden funktionieren, wenn wir die Car-Klasse später ändern.

Die update()-Methode bleibt leer, da das Auto nicht läuft.

toString() funktioniert genauso wie die toString()-Methode des Autos.

Das schließt die EngineOff-Klasse ab.

Bevor wir den Rest der anderen Zustandsklassen erstellen, ändern wir die Car-Klasse und konvertieren sie in eine eigene Zustandsmaschine.


Schritt 18: Die Car-Zustandsmaschine

Wichtig: Erstellen Sie eine doppelte Car-Klasse, bevor Sie das folgende Verfahren ausführen.  Eine Textkopie würde ausreichen, aber speichern Sie sie als Referenz für später.

Anstatt die Änderungen Element für Element durchzugehen, kopiere einfach den unten stehenden Code und füge dann den Inhalt deiner Auto-Klasse ein und ersetze ihn.

Lassen Sie uns über die Änderungen gehen.

Beginnt bei der Definition von Variablen.  Sie werden feststellen, dass die vier Zustände den Typ in IState geändert haben und keine statischen Konstanten mehr sind.

Als nächstes ruft der Konstruktor init() auf, der wiederum initializeState() aufruft.  Alle Zustandsklassen werden durch diese Methode instanziiert.

Dann kommt der einfache Teil, keine Switch-Anweisungen mehr.  Das Auto delegiert die Aktionen nur an den aktuellen Status.  Sehen Sie turnKeyOff() runter zu reFuel()

Die Methode consumeFuel() musste für EngineOn und EngineDriveForward öffentlich zugänglich werden.

Und dann die beiden Methoden, die wir in der reFuel()-Methode von EngineOff verwendet haben - hasFullTank() und refillWithFuel().

Unter ihnen sind die expliziten Getter, die Zugriff für alle vier Zustände bereitstellen.  Es mag wie ein merkwürdiges Protokoll erscheinen, aber es ist nur Verkapselung bei der Arbeit.

Das changeState() tut genau das, was es sagt, es ändert den _currentState.

Nach der strengen Regel von OOP kann die _engineTimer-Eigenschaft erneut über diese beiden Methoden aufgerufen und geändert werden: get engineTimer() und set engineTimer().

print() wird jetzt den String-Parameter nur an eine trace()-Anweisung übergeben.  Und dann die toString()-Methode.


Schritt 19: Erstellen der anderen drei Zustände

Um die Erstellung der drei anderen Klassen zu vereinfachen, wechseln Sie in die Klasse Car innerhalb der initialize()-Methode.  Setzen Sie den Cursor in das Wort "EngineOn" und drücken Sie "CTRL + SHIFT + 1", um eine Eingabeaufforderung zu generieren.  Wählen Sie "Neue Klasse erstellen" und drücken Sie "ENTER".

Passen Sie die Informationen wie in der Abbildung unten an und klicken Sie auf "OK".

description of image

Das ähnelt Schritt 16 beim Erstellen der EngineOff-Klasse.  Nur dieses Mal haben wir FD Shortcuts benutzt.  Außerdem werden Sie feststellen, dass das car-Objekt im Konstruktor bei der Instanziierung übergeben wurde.  Vergessen Sie nicht, das "$"- Zeichen zum car-Parameter für Ihren Konstruktor und die einzige Klassenvariable _car oben hinzuzufügen.

Vergleichen Sie es mit dem folgenden Code.

Gehen Sie nun zurück in die Methode initialize() in Car und wiederholen Sie den Vorgang für die letzten beiden verbleibenden Statusklassen.


Schritt 20: Abschließen der Klasse EngineOn

Denken Sie, Sie können es mit der Car.txt (Duplikat) und Zustandsübergangstabelle zusammensetzen?

Probieren Sie es aus, folgen Sie einfach Schritt 17 und Sie werden es gut machen.  Denken Sie daran, dass Sie jetzt an Aktionsergebnissen für ENGINE_ON arbeiten.

Ausgezeichnet!  Wenn Sie fertig sind, vergleichen Sie Ihren Code mit den Klassen im Ordner "StatePatternPartial1", die im Quelldownload enthalten sind.


Schritt 21: Letzte Prüfung

Wenn Sie mit allen Ihren State-Klassen fertig sind, gehen Sie zurück zu Main.as und führen Sie Ihre Anwendung aus.

Hoffentlich lief alles gut und Sie haben keine Fehler bekommen.  Informationen sollten beginnen, aus dem Ausgabefeld zu drucken.

Wir beenden den ersten Teil des Tutorials hier.  Für den zweiten Teil beginnen wir mit den beiden anderen Zuständen "EngineDriveReallyFast" und "EngineDriveBackward".  Dann fügen wir Steuerelemente für Animation und Sound hinzu, um zu zeigen, wie einfach das Ändern und Skalieren ist.


Schlussfolgerung

Von all den Designmustern, mit denen ich gespielt habe, ist diese bei mir die wichtigste (vor allem im Bereich Game Design).  Sie werden sehen, warum, wenn Sie damit beginnen, Ihr nächstes Spielobjekt zu erstellen.  Warum versuchen Sie nicht, die Pistole zu erstellen, die ich am Anfang dieses Tutorials erwähnt habe? Sie werden genießen, es zu erstellen!  Vergessen Sie nicht, klein anzufangen.  Erstellen Sie es immer von Procedural FSM und konvertieren Sie es dann in das Zustandsmuster. 

Hier sind die Schritte: 

  1. Skizzieren Sie die Zustandsübergangstabelle für Ihr Objekt. 
  2. Erstellen Sie Ihr prozedurales FSM-Objekt.
  3. Wenn Procedural FSM funktioniert, müssen Sie es in das Zustandsmuster konvertieren, wenn Sie viel mehr Funktionen und/oder Zustände hinzufügen müssen. 
  4. Erstellen Sie zuerst Ihre IState-Schnittstelle.
  5. Erstellen Sie die erste/Standard-State-Klasse (siehe State Transition Table und Prozedurale FSM-Aktionen). 
  6. Duplizieren Sie eine Kopie Ihres prozeduralen FSM-Objekts, und erlauben Sie dann den öffentlichen Zugriff auf alle Eigenschaften, die die Statusklassen steuern müssen. 
  7. Erstellen Sie den Rest der State-Klassen.
  8. Fügen Sie Merkmale/Zustände gemäß Ihren Anforderungen hinzu.  Diese präsentieren sich normalerweise, während Sie an Ihren Zustandsaktionen arbeiten. 

Wir sehen uns im zweiten Teil! 

Wie immer, für Kommentare, Vorschläge oder Bedenken, schreiben Sie bitte eine Notiz in den Kommentarbereich. 

Danke fürs Lesen!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.