Zunächst beziehe ich mich nicht auf das Szenenmanagement. Ich definiere den Spielstatus lose als jede Art von Status in einem Spiel, der Auswirkungen darauf hat, ob Benutzereingaben aktiviert werden sollen oder ob bestimmte Akteure vorübergehend deaktiviert werden sollen usw.
Nehmen wir als konkretes Beispiel an, es ist ein Spiel des klassischen Battlechess. Nachdem ich versucht habe, die Figur eines anderen Spielers zu nehmen, wird eine kurze Kampfsequenz abgespielt. Während dieser Sequenz darf der Spieler keine Steine bewegen. Wie würden Sie diese Art von Zustandsübergang verfolgen? Eine endliche Zustandsmaschine? Eine einfache Boolesche Prüfung? Es scheint, dass Letzteres nur für ein Spiel mit sehr wenigen Zustandsänderungen dieser Art gut funktionieren würde.
Ich kann mir viele einfache Möglichkeiten überlegen, wie dies mit endlichen Zustandsautomaten gehandhabt werden kann, aber ich kann auch sehen, wie sie schnell außer Kontrolle geraten. Ich bin nur neugierig, ob es eine elegantere Möglichkeit gibt, Spielzustände / -übergänge im Auge zu behalten.
Antworten:
Ich bin einmal auf einen Artikel gestoßen, der Ihr Problem ganz elegant löst. Es ist eine grundlegende FSM-Implementierung, die in Ihrer Hauptschleife aufgerufen wird. Ich habe den grundlegenden Überblick über den Artikel im Rest dieser Antwort skizziert.
Ihr grundlegender Spielstatus sieht folgendermaßen aus:
Jeder Spielzustand wird durch eine Implementierung dieser Schnittstelle dargestellt. Für Ihr Battlechess-Beispiel könnte dies folgende Zustände bedeuten:
Zustände werden in Ihrer State Engine verwaltet:
Beachten Sie, dass jeder Status irgendwann einen Zeiger auf CGameEngine benötigt, damit der Status selbst entscheiden kann, ob ein neuer Status eingegeben werden soll. Der Artikel schlägt vor, die CGameEngine als Parameter für HandleEvents, Update und Draw zu übergeben.
Am Ende befasst sich Ihre Hauptschleife nur mit der State Engine:
quelle
Ich beginne damit, so etwas so einfach wie möglich zu handhaben.
Dann füge ich die Checks gegen diese Boolesche Flagge an den entsprechenden Stellen hinzu.
Wenn ich später herausfinde, dass ich mehr Spezialfälle benötige - und nur das -, berücksichtige ich etwas Besseres. Es gibt normalerweise 3 Ansätze, die ich verfolgen werde:
enum { PRE_MOVE, MOVE, POST_MOVE }
und fügen Sie die Übergänge hinzu, wo immer dies erforderlich ist. Dann kann ich anhand dieser Aufzählung prüfen, wo ich früher anhand der Booleschen Flagge geprüft habe. Dies ist eine einfache Änderung, die jedoch die Anzahl der zu überprüfenden Dinge verringert und es Ihnen ermöglicht, switch-Anweisungen zu verwenden, um das Verhalten effektiv zu verwalten usw.pieceSelectionManager->disable()
zu Beginn der Sequenz callen oder ähnliches undpieceSelectionManager->enable()
. Sie haben im Wesentlichen immer noch Flags, aber jetzt sind sie näher an dem Objekt gespeichert, das sie steuern, und Sie müssen keinen zusätzlichen Status in Ihrem Spielcode beibehalten.Im Allgemeinen muss ich in Bezug auf Sonderfälle nie weiter gehen, daher glaube ich nicht, dass das Risiko besteht, dass es schnell außer Kontrolle gerät.
quelle
http://www.ai-junkie.com/architecture/state_driven/tut_state1.html ist ein hübsches Tutorial zur Verwaltung des Spielstatus! Sie können es entweder für Spielelemente oder für ein Menüsystem wie oben verwenden.
Er fängt an, über das State Design Pattern zu unterrichten , setzt dann a um
State Machine
und erweitert es sukzessive immer weiter. Es ist eine sehr gute Lektüre! Sie erhalten ein solides Verständnis dafür, wie das gesamte Konzept funktioniert und wie es auf neue Arten von Problemen angewendet werden kann.quelle
Ich versuche, keine Zustandsmaschine und keine Booleschen Werte für diesen Zweck zu verwenden, da beide nicht skalierbar sind. Beide verwandeln sich in Chaos, wenn die Anzahl der Staaten wächst.
Normalerweise entwerfe ich das Gameplay als eine Abfolge von Aktionen und Konsequenzen. Jeder Spielstatus ist natürlich, ohne dass er separat definiert werden muss.
Zum Beispiel in Ihrem Fall mit der Deaktivierung der Spielereingabe: Sie haben einige Benutzereingabehandler und einige Ingame-visuelle Anzeigen, dass die Eingabe deaktiviert ist. Sie sollten sie daher zu einem Objekt oder einer Komponente machen. Um die Eingabe zu deaktivieren, müssen Sie nur das gesamte Objekt deaktivieren Synchronisieren Sie sie in einer Zustandsmaschine oder reagieren Sie auf einen Booleschen Indikator.
quelle