Spielzustand-Automaten

Aus Spieleprogrammierer-Wiki
(Unterschied zwischen Versionen)
Wechseln zu: Navigation, Suche
[gesichtete Version][gesichtete Version]
K (Stapelverarbeitung von Zuständen)
(Grundidee und Architektur)
Zeile 10: Zeile 10:
 
[[Datei:uml_states.png|miniatur|UML-Klassendiagramm eines Spielzustand-Automaten]]
 
[[Datei:uml_states.png|miniatur|UML-Klassendiagramm eines Spielzustand-Automaten]]
  
Die Grundidee der Spielzustand-Automaten lässt sich in zwei Klassen teilen: Den Zustands-Manager <tt>StateManager</tt> und ein Interface <tt>State</tt>. Jedes Spiel definiert eine Menge an Zuständen in Form einer Klasse, die das Interface <tt>State</tt> implementiert. Der <tt>StateManager</tt> kennt und besitzt alle Zustände und identifiziert diese über eine ID. Im Folgenden wird auf beide Klassen näher eingegangen.
+
Die Grundidee der Spielzustand-Automaten lässt sich in zwei Klassen teilen: Den Zustands-Manager <tt>StateManager</tt> und eine Schnittstelle <tt>State</tt>. Jedes Spiel definiert eine Menge an Zuständen in Form von Klassen, die die Schnittstelle <tt>State</tt> implementieren. Der <tt>StateManager</tt> kennt und besitzt alle Zustände und identifiziert diese über eine ID. Im Folgenden wird auf beide Klassen näher eingegangen.
  
 
=== State ===
 
=== State ===
  
<tt>State</tt> definiert ein Interface für den <tt>StateManager</tt>. Dieses wird von den konkreten Spielzuständen implementiert. Für einen Spielzustand können abhängig von der Situation unterschiedliche Schnittstellen interessant sein. Grundsätzlich können folgende prinzipiell notwendig sein:
+
<tt>State</tt> definiert eine Schnittstelle für Spielzustände, die vom <tt>StateManager</tt> verwaltet werden. Für jeden konkreten Spielzustand wird eine Klasse benötigt, die die <tt>State</tt>-Schnittstelle implementiert. Die Schnittstelle enthält eine Reihe von Methoden, die beim Eintritt bestimmter Ereignisse aufgerufen werden:
  
 
* <tt>'''OnEnter'''</tt>: Der <tt>StateManager</tt> ruft diese Methode auf, wenn von einem anderen Zustand zu diesem Zustand gewechselt wird. Dadurch können z.B. Variablen zurückgesetzt, Eingangsanimationen gestartet oder ein Musikstück abgespielt werden.
 
* <tt>'''OnEnter'''</tt>: Der <tt>StateManager</tt> ruft diese Methode auf, wenn von einem anderen Zustand zu diesem Zustand gewechselt wird. Dadurch können z.B. Variablen zurückgesetzt, Eingangsanimationen gestartet oder ein Musikstück abgespielt werden.
Zeile 20: Zeile 20:
 
* <tt>'''OnUpdate'''</tt>: In dieser Funktion wird die Logik des Zustands berechnet. Im Falle des Zustands ''Spiel'' werden üblicherweise KI, Animationen und Physik aktualisiert.
 
* <tt>'''OnUpdate'''</tt>: In dieser Funktion wird die Logik des Zustands berechnet. Im Falle des Zustands ''Spiel'' werden üblicherweise KI, Animationen und Physik aktualisiert.
 
* <tt>'''OnRender'''</tt>: Hier findet das gesamte Zeichnen für den aktuellen Zustand statt.
 
* <tt>'''OnRender'''</tt>: Hier findet das gesamte Zeichnen für den aktuellen Zustand statt.
* <tt>'''NextState'''</tt>: Liefert den nächsten Zustand, der bei einem Zustandswechsel gewählt werden soll.
 
  
 
=== StateManager ===
 
=== StateManager ===
Zeile 26: Zeile 25:
 
Der <tt>StateManager</tt> verwaltet alle für das Spiel möglichen Zustände. Dazu werden ihm alle Zustände durch <tt>AddState</tt> bekannt gemacht. Für den <tt>StateManager</tt> ist immer genau ein Zustand aktuell. Dieser lässt sich mit der Methode <tt>SetState</tt> festlegen.
 
Der <tt>StateManager</tt> verwaltet alle für das Spiel möglichen Zustände. Dazu werden ihm alle Zustände durch <tt>AddState</tt> bekannt gemacht. Für den <tt>StateManager</tt> ist immer genau ein Zustand aktuell. Dieser lässt sich mit der Methode <tt>SetState</tt> festlegen.
  
Prinzipiell verwendet man bei Spielen getrennte Logik für Update- und Render-Funktionalität. Daher unterscheidet der <tt>StateManager</tt> auch zwischen diesen beiden Vorgängen, indem es getrennte Methoden gibt. Diese rufen vom aktuellen Zustand <tt>OnUpdate</tt> bzw. <tt>OnRender</tt> auf.
+
Prinzipiell verwendet man bei Spielen getrennte Logik für Update- und Render-Funktionalität. Daher unterscheidet der <tt>StateManager</tt> auch zwischen diesen beiden Vorgängen, indem er getrennte Methoden besitzt. Diese rufen vom aktuellen Zustand <tt>OnUpdate</tt> bzw. <tt>OnRender</tt> auf.
  
 
=== Stapelverarbeitung von Zuständen ===
 
=== Stapelverarbeitung von Zuständen ===
  
Neben dem simplen Setzen von Zuständen ist die Abfolge von Zustandswechsel ein interessantes Thema. Dieses Problem lässt sich durch einen Stack sehr gut lösen. Der <tt>StateManager</tt> besitzt einen Stack, der eine Menge an Zuständen referenziert. Dabei gilt das [http://de.wikipedia.org/wiki/Last_In_–_First_Out LIFO-Prinzip] (''Last In – First Out''). Mit Hilfe der Methoden <tt>PushState</tt> lässt sich ein neuer Zustand auf den Stapel packen, der auch gleichzeitig der Aktive ist. Das Gegenstück lautet <tt>PopState</tt> und nimmt den zuletzt eingefügten Zustand vom Stapel. Durch dieses Prinzip gestalten sich Zustandsübergänge durch eine Kombination aus <tt>PushState</tt> und <tt>PopState</tt>. Hier ein einfaches Beispiel:
+
Neben dem simplen Setzen von Zuständen ist die Abfolge von Zustandswechsel ein interessantes Thema. Es bietet sich hier die Benutzung eines Stapels (''Stack'') an. Der <tt>StateManager</tt> besitzt einen Stapel, der eine Menge an Zuständen referenziert. Dabei gilt das [http://de.wikipedia.org/wiki/Last_In_–_First_Out LIFO-Prinzip] (''Last In – First Out''). Mit Hilfe der Methoden <tt>PushState</tt> lässt sich ein neuer Zustand auf den Stapel packen, der auch gleichzeitig der Aktive ist. Das Gegenstück lautet <tt>PopState</tt> und nimmt den zuletzt eingefügten Zustand vom Stapel. Durch dieses Prinzip gestalten sich Zustandsübergänge durch eine Kombination aus <tt>PushState</tt> und <tt>PopState</tt>. Hier ein einfaches Beispiel:
  
 
Ein Spiel besitzt zwei Zustände: ''Hauptmenü'' und ''Spiel''. Der <tt>StateManager</tt> hat vorerst einen leeren Stapel. Beim Starten des Programmes wird der Zustand ''Hauptmenü'' mit <tt>PushState</tt> als erster Zustand gesetzt. Nun entscheidet sich der Spieler, ein neues Spiel zu starten. Im Programm wird mit <tt>PushState</tt> der Zustand ''Spiel'' auf den Stapel gepackt. Dadurch ist ''Spiel'' der aktuelle Zustand. Nachdem der Spieler sein Spiel gespielt und verloren hat, möchte er das Spiel erneut mit einem anderen Schwierigkeitsgrad spielen und beendet das Spiel, um in das Hauptmenü zu gelangen. Dazu wird <tt>PopState</tt> aufgerufen, wodurch der Zustand ''Spiel'' vom Stapel genommen wird und ''Hauptmenü'' wieder der aktuelle Zustand ist.
 
Ein Spiel besitzt zwei Zustände: ''Hauptmenü'' und ''Spiel''. Der <tt>StateManager</tt> hat vorerst einen leeren Stapel. Beim Starten des Programmes wird der Zustand ''Hauptmenü'' mit <tt>PushState</tt> als erster Zustand gesetzt. Nun entscheidet sich der Spieler, ein neues Spiel zu starten. Im Programm wird mit <tt>PushState</tt> der Zustand ''Spiel'' auf den Stapel gepackt. Dadurch ist ''Spiel'' der aktuelle Zustand. Nachdem der Spieler sein Spiel gespielt und verloren hat, möchte er das Spiel erneut mit einem anderen Schwierigkeitsgrad spielen und beendet das Spiel, um in das Hauptmenü zu gelangen. Dazu wird <tt>PopState</tt> aufgerufen, wodurch der Zustand ''Spiel'' vom Stapel genommen wird und ''Hauptmenü'' wieder der aktuelle Zustand ist.

Version vom 7. November 2011, 17:18 Uhr

Klicke hier, um diese Version anzusehen.

Meine Werkzeuge
Namensräume
Varianten
Aktionen
Navigation
Werkzeuge