Wie kann man in einer endlichen Zustandsmaschine zwischen Zuständen wechseln und Zustände mischen?

7

Ich verstehe nicht, wie man eine endliche Zustandsmaschine mit der vom Spieler kontrollierten Entität verwendet.

Zum Beispiel habe ich ein Spiel im Mario-Stil (2d-Plattform). Ich kann springen, rennen, gehen, Schaden nehmen, schwimmen usw. Mein erster Gedanke war also, diese Aktionen als Zustände zu verwenden. Aber was passiert, wenn Sie rennen, wenn Sie Schaden nehmen? Oder gleichzeitig springen, Schaden nehmen und schießen?

Ich möchte dem Player nur Funktionen (Aktionen) auf saubere Weise hinzufügen (nicht für alle Aktionen in der Entitätsaktualisierung verwenden).

Juakob
quelle
2
Die Frage ist etwas bizarr; Warum sollten Aktionen Staaten im FSM sein? Warum sollten sie keine Eingaben in das FSM sein?

Antworten:

7

Ich denke, der normale Weg ist, mehrere Zustandsautomaten zu haben. Auf diese Weise können Sie sich an atomare Zustände halten, was Ihr Leben oft viel einfacher macht, als mit komplexen Zuständen umgehen zu müssen.

Zum Beispiel:

  • Schadensmodus: Normal, unverwundbar (wie bei einem Treffer), unbesiegbar (wie bei einem Stern)
  • Tempo: Gehmodus, Laufmodus
  • Fähigkeiten: Normal, Super, Feuer, Fliegen
  • Bewegungsart: Gehen, Schwimmen, Fliegen

In der objektorientierten Gestaltung gibt es dafür das Zustandsmuster . Es läuft darauf hinaus, eine Schnittstelle pro Zustandsmaschine zu haben. Und eine Klasse pro möglichem Zustand, die diese Schnittstelle implementiert.

Ein Beispiel: Es gibt eine Schnittstelle DamageMode und Unterklassen NormalDamageMode, InvulnerableDamageMode und InvincibleDamageMode. Immer wenn der Spieler mit einem Feind kollidiert, wird die Methode DamageMode.collision (Feind) aufgerufen. Es wird von der Klasse behandelt, die für den aktuellen Status verantwortlich ist.

Wenn also DamageMode == NormalDamageMode ist, wird der Player beschädigt und die Statusvariable auf InvulnerableDamageMode gesetzt. Im InvulnerableDamageMode passiert nichts und im InvincibleDamageMode wird der Feind beschädigt. Natürlich muss es Timer geben, um von InvulnerableDamageMode und InvincibleDamageMode zu NormalDamageMode zurückzukehren.

Der Hauptvorteil des Statusmusters im Vergleich zu if-elseif-elseif-elseif-Blöcken besteht darin, dass Sie Ihren Code besser strukturieren können.

Hendrik Brummermann
quelle
+1 für die Herstellung vieler kleiner FSMs anstelle einer großen. Körnigkeit ist hier sehr nützlich.
Tenpn
Ich mag die Idee mehrerer Zustandsautomaten. Aber wie werden sie integriert, um mit einer Entität zusammenzuarbeiten? Werden sie parallel aktualisiert? oder sind sie in einer Entitätszustandsmaschine verschachtelt?
Dani
@Dani, jede Zustandsmaschine wird als Attribut der Entitätsobjekte referenziert. Die meisten von ihnen sind unabhängig, zum Beispiel können Sie mit kleinen, Super-, Feuer- und Fliegenfähigkeiten unbesiegbar sein. Einige Ereignisse lösen mehrere Zustandsübergänge aus: Wenn Sie beispielsweise von einem Feind getroffen werden, verringert sich die Fähigkeit und der Schadensmodus wird unverwundbar. Dies lässt nur wenige Fälle übrig, in denen zwei Zustandsautomaten tatsächlich miteinander verbunden sind. Zum Beispiel Force Run-Modus, während er unbesiegbar ist.
Hendrik Brummermann
7

Zustände sind keine Aktionen, in Ihrem Spiel steuern sie, wie der Charakter aktualisiert wird (z. B. könnte jeder Zustand seine eigene Funktion update () haben).

Schauen Sie sich das Diagramm auf dieser Seite an: http://en.wikipedia.org/wiki/State_diagram . Die Staaten erzählen uns etwas über die Welt (die Tür ist offen oder geschlossen). Die Aktionen zeigen uns, was die Welt von einem Staat in einen anderen bringt.

In Ihrem Fall könnten Sie Zustände haben wie:

  • Springen
  • Laufen
  • Schmerzen haben
  • fallen
  • tot

Und der Übergang zwischen Staaten (die Ereignisse / Pfeile zwischen Staaten) wären Eingaben von Spielern und Reaktionen auf die Welt, wie zum Beispiel:

  • von einem Monster getroffen
  • Sprungtaste gedrückt
  • Aufnahmetaste gedrückt

Jeder Staat muss prüfen, ob relevante Ereignisse aufgetreten sind. In der Regel erfolgt dies mit if-Anweisungen.

Aber was passiert, wenn du rennst, wenn du Schaden nimmst?

Das hit by monsterEreignis würde ausgelöst und den Spieler in den in painZustand versetzen.

oder springen, Schaden nehmen und gleichzeitig schießen?

Der Spieler würde wieder in den in painZustand übergehen, in dem Sie Ihr "Hit" -Sprite anzeigen könnten, das den rückwärts fallenden Charakter zeigt.

Sie werden if-Anweisungen wahrscheinlich nicht entkommen, aber Sie können tief verschachtelte Anweisungen vermeiden.

CiscoIPPhone
quelle