Soweit ich das beurteilen kann, haben die meisten Spiele eine Art "Spielstatus-System", das zwischen den verschiedenen Spielstatus wechselt. Dies können Dinge wie "Intro", "MainMenu", "CharacterSelect", "Loading" und "Game" sein.
Zum einen ist es durchaus sinnvoll, diese in ein staatliches System zu zerlegen. Immerhin sind sie uneinheitlich und müssten ansonsten in einer großen switch-Anweisung stehen, die offensichtlich chaotisch ist. und sie sind sicherlich gut durch ein staatliches System vertreten. Gleichzeitig schaue ich auf den Zustand "Spiel" und frage mich, ob an diesem Ansatz des Zustandssystems etwas nicht stimmt. Weil es wie der Elefant im Raum ist; Es ist RIESIG und offensichtlich, aber niemand stellt den Ansatz des Spielstatus-Systems in Frage.
Mir kommt es albern vor, dass "Spiel" auf die gleiche Ebene gestellt wird wie "Hauptmenü". Es gibt jedoch keine Möglichkeit, den Status "Spiel" aufzulösen.
Ist ein Spielstatus-System der beste Weg? Gibt es eine andere, bessere Technik, um den "Spielstatus" zu verwalten? Ist es in Ordnung, einen Intro-Status zu haben, der einen Film zeichnet und auf die Eingabe wartet, und dann einen Lade-Status, der den Ressourcen-Manager durchläuft, und dann den Spiel-Status, der praktisch alles macht ? Kommt dir das nicht auch irgendwie unausgeglichen vor? Vermisse ich etwas?
quelle
Sicher, der Spielstatus wäre riesig, aber es gibt keinen Grund, warum der Spielstatus selbst keine Zustandsmaschine zur Verwaltung seiner Daten enthalten kann. Hierarchische Zustandsautomaten sind nützlich.
quelle
Ich stelle mir immer gerne jeden "Zustand" als "Szene" vor. Das Eröffnungsvideo ist also nur eine statische Szene. Die Credits sind eine Szene. Das Menü ist eine Szene. Der einzige Unterschied zwischen allen besteht in der Interaktivität und der Spielelogik.
quelle
Damit habe ich eigentlich auch Probleme.
Nehmen wir an, Sie haben ein Spiel.
Anstatt zu machen ‚Game‘ ein Zustand wie ‚Laden‘, ‚Hauptmenü‘ usw. - IMO es besser ist , Spiel zu lassen , hat mehrere Staaten:
"Laden" - "Menü anzeigen" - "Angehalten" usw.
Das Spiel läuft noch, aber wenn das Hauptmenü angezeigt wird, befindet es sich im Modus "Menü anzeigen".
Und wenn sich das Spiel in keinem bestimmten Zustand befindet, läuft es einfach.
Zumindest für mich ist das viel sinnvoller. :)
quelle
Ein Online-Programm (im herkömmlichen Sinne von Online, dh, es wird ständig ausgeführt und reagiert auf Eingaben, anstatt dass es mit dem Internet verbunden ist) besteht normalerweise aus drei Dingen:
Im Allgemeinen sind diese 3 verwandt und ändern sich gleichzeitig. Wenn Sie beispielsweise einen Begrüßungsbildschirm anzeigen, ordnen Sie alle Tasten einem Befehl zum Schließen des Bildschirms zu, und die Aktualisierung blendet möglicherweise eine Grafik langsam ein, wobei die Ausgabe nur diese Grafik anzeigt. Beim Spielen eines Spiels werden die Tasten möglicherweise unterschiedlichen Befehlen zugeordnet, und das Update ändert die Eigenschaften vieler Objekte im Spiel.
Wenn Sie es so betrachten, ist es sinnvoll, ein Intro von der Charaktererstellung und vom eigentlichen Spiel zu trennen: Jedes hat seine eigenen Eingabe-, Aktualisierungs- und Ausgaberegeln. Sie sind fast wie eigenständige Programme, die Daten und Bibliothekscode gemeinsam nutzen. Aus diesem Grund ist es in der Regel sinnvoll, nur einen Spielstatus zu haben, da das Gameplay durchgehend ziemlich homogen ist.
Natürlich gibt es keinen Grund, warum Sie dort nicht mehrere Zustände haben könnten, wenn Sie tatsächlich verschiedene Arten von Spiel haben (z. B. ein RPG-Beispiel - Weltkarte, Stadtplan, Zwischensequenz, Kampf), mit unterschiedlichen Eingaben, Aktualisierungen und Ausgaben auch anstelle von nur 1 Spielstatus. Aber es hängt von deinem Spiel ab.
quelle
Ich sehe es anders. "Menü", "HighScores", "Credits" oder was auch immer Sie haben, könnten als eine andere Ebene betrachtet werden, und dann ist dieser Zustand nicht unbedingt leichter als Ihr "Spiel" -Zustand (der Spielzustand hat einfach mehr Entitäten im Allgemeinen). und andere, aber am Ende ist es nur eine andere Ebene, auf der die Entitäten mehr prädikatibles Verhalten zeigen und die "Karten" im Allgemeinen weniger kompliziert sind.
Wenn Sie diese Änderung in Ihrem Denken vornehmen, werden Sie definitiv aus dem "langweiligen Menü" -Syndrom herausgezogen.
quelle
In meinem Spiel habe ich:
Der Execution Manager , der die Anwendung (das Spiel) initialisiert, Ressourcen lädt, Ressourcen beim Beenden der Anwendung freigibt usw. Er initialisiert Application Engine, GameViewEngine, GameLogicEngine.
Game State Manager , der sich in der GameLogicEngine befindet und für die Steuerung der Dinge im Zusammenhang mit der Hauptschleife des Spiels verantwortlich ist: Kollisionserkennung, Physikberechnung, Tastaturlesen, mathematische Operationen usw.
Anfangs hatte ich nur einen Game State Manager, der Teil meiner GameLogicEngine war. Ich hatte jedoch einige Schwierigkeiten, die Initialisierung der Hauptsubsysteme (GameLogic, ApplicationEngine, ...) zu kontrollieren. Es hätte getan werden können, aber es war unordentlicher, imo.
Jetzt sieht es für mich transparenter aus und ich bin mit dem Design zufrieden.
quelle
Benenne den 'Game'-Status in' Gameplay 'um. Dann scheint deine Logik besser zu sein; Sie hören auf zu spielen, um zum Menü zu gelangen: Sie verlassen den Gameplay-Status, um in den MainMenu-Status zu gelangen.
Ich denke auch, dass Dinge wie Pause, bei denen sich das Spiel im selben Zustand wie bei der Pause befinden müsste, keine getrennten Zustände sein sollten. Vielleicht Kinderzustände und Nisten? Das Gameplay hat ein Pausenmenü.
quelle
Ich denke, dass es eine gute Methode gibt, die als Spielstatusstapel bezeichnet wird. Ich habe keine Zeitungen oder Artikel darüber gesehen, aber es hat sich ein bisschen lautstark verbreitet. Im Wesentlichen wird der oberste Spielstatus auf dem Stapel zuerst aufgerufen und kann mit Eingabe / Rendern usw. alles Mögliche tun. Der oberste Spielstatus ist der einzige, der Push- oder Pop-Status zulässt.
In meiner Engine sind Spielzustände eigentlich nur Listen von Spieleinheiten. Ich habe dann Entitäten, die als Menüs arbeiten. Meine Menüzustände unterbrechen entweder das Spiel (indem der nächste Gegenstand auf dem Stapel nicht aktualisiert wird), aber lassen Sie die anderen Zustände ihre Modelle an den Renderer senden, sodass mein Pausenmenü (das nicht den gesamten Bildschirm abdeckt) immer noch angezeigt wird hat das spiel rendern im rücken.
Ich hoffe, das gibt eine Vorstellung von einem etwas anderen System, das nicht auf einer Zustandsmaschine basiert.
quelle
Das ist vollkommen in Ordnung. Oder zumindest ist es eine Verbesserung gegenüber "einem großen hässlichen Schalter, abhängig vom Zustand des Spiels".
Ich möchte darauf hinweisen, dass Sie in den meisten Spielen bereits eine Art Finite-State-Maschine benötigen, um mit einfacher Entity-KI umgehen zu können. Das typische Beispiel sind Feinde, die sich im Ruhezustand befinden, angreifen oder sterben.
Wenn Sie eine ausreichend abstrahierte Zustandsmaschine haben, können Sie diese sowohl für das Spielobjekt als auch für Ihre KI wiederverwenden. plötzlich "investieren" Sie nicht mehr viel in den Spielstatus - stattdessen verwenden Sie den Code, den Sie sowieso verwendet haben.
Schamloses Selbst-Plug-In: Ich habe eine solche Finite-State-Maschine in meine Lua-Spielebibliothek MiddleClass (konkret das Add-On MindState) implementiert. Hier erfahren Sie, wie Sie damit einen Spielstatus erstellen .
quelle
Ein anderer Ansatz besteht darin, ein Konzept aus der Welt der funktionalen Programmierung zu verwenden, das als diskriminierte Union bezeichnet wird . Während diese normalerweise in FP-Sprachen vorkommen, können Sie sie mithilfe von Klassen emulieren .
Grundsätzlich ist eine diskriminierte Union ein Typ, der immer einer der
n
Fälle ist, und die gespeicherten Daten können von Fall zu Fall variieren.Beispielsweise:
Hier kann unser
GameState
Typ entwederMenu
oder seinPlaying
. Wenn dies der Fall istMenu
, enthält es einMenuState
Objekt. Wenn dies der Fall istPlaying
, enthält es einSimulationState
Objekt.Zum Update würden wir
match
auf den Stand, und eine andere Funktion entsprechend aufrufen:Und ähnlich zum Rendern:
Ein Vorteil dieses Ansatzes besteht darin, dass Sie Dinge über Zustände (wie Ressourcen) hinweg einfacher handhaben können, ohne Globals oder "Service" -Objekte zu übergeben.
quelle