Diskussion:Spielzustand-Automaten

Aus Spieleprogrammierer-Wiki
(Unterschied zwischen Versionen)
Wechseln zu: Navigation, Suche
(Verwendung eines Stacks)
(Verwendung eines Stacks)
Zeile 26: Zeile 26:
  
 
Warum hält man es denn nicht erst mal einfach und erweitert es dann Schritt für Schritt. Ist ja im Menü sogar so vorgesehen, dass hinterher Erweiterungen gezeigt werden. So würde ich vorschlagen, zuerst eine Version ohne Stack zu zeigen. Auch muss der Folgestate ja nicht im State selbst gesetzt sein. Man kann doch den aktuellen State selbst entscheiden lassen. Zum Beispiel könnte ein Intro-State dann Abfragen ob eine Taste gedrückt wird und in dem Fall zum Menü weiterleiten. Falls nach 5 Sekunden nichts passiert, könnte der Intro-State zu einer Demo weiterleiten. Falls hier etwas gedrückt wird gehts weiter zum Menü, ansonsten nach einer Zeit wieder zum Intro. Jeder State überlegt für sich wie er wann weiterleitet. Ein einfaches Statepattern also. Als Erweiterung kann man dann auf die Variante mit dem Stack eingehen. Klar ist dies nicht viel komplizierter, aber diejenigen die von Stacks noch nichts gehört haben schreckt es vielleicht erst einmal ab. Außerdem gibt es mit Sicherheit genug Spiele, die diese Funktionalität überhaupt nicht brauchen. So würde die die Variante mit Stack dann als Erweiterung ansehen, die dann durch die Version mit Transparenz noch weiter erweitert werden könnte. Lieber alles Schritt für Schritt erklären. --[[Benutzer:Schorsch|Schorsch]]
 
Warum hält man es denn nicht erst mal einfach und erweitert es dann Schritt für Schritt. Ist ja im Menü sogar so vorgesehen, dass hinterher Erweiterungen gezeigt werden. So würde ich vorschlagen, zuerst eine Version ohne Stack zu zeigen. Auch muss der Folgestate ja nicht im State selbst gesetzt sein. Man kann doch den aktuellen State selbst entscheiden lassen. Zum Beispiel könnte ein Intro-State dann Abfragen ob eine Taste gedrückt wird und in dem Fall zum Menü weiterleiten. Falls nach 5 Sekunden nichts passiert, könnte der Intro-State zu einer Demo weiterleiten. Falls hier etwas gedrückt wird gehts weiter zum Menü, ansonsten nach einer Zeit wieder zum Intro. Jeder State überlegt für sich wie er wann weiterleitet. Ein einfaches Statepattern also. Als Erweiterung kann man dann auf die Variante mit dem Stack eingehen. Klar ist dies nicht viel komplizierter, aber diejenigen die von Stacks noch nichts gehört haben schreckt es vielleicht erst einmal ab. Außerdem gibt es mit Sicherheit genug Spiele, die diese Funktionalität überhaupt nicht brauchen. So würde die die Variante mit Stack dann als Erweiterung ansehen, die dann durch die Version mit Transparenz noch weiter erweitert werden könnte. Lieber alles Schritt für Schritt erklären. --[[Benutzer:Schorsch|Schorsch]]
 +
 +
: Das Problem ohne Stack ist, dass du dir ggf. irgendwie merken musst, woher du gekommen bist. Außerdem: Mal angenommen du gehst vom Spiel in die Optionen - dann wäre es nicht toll, wenn das Spiel "OnLeave" erhalten würde, denn eigentlich wird es ja gar nicht verlassen, sondern nur von den Optionen verdeckt. Kommst du dann wieder zurück ins Spiel, wird dort "OnEnter" aufgerufen und das Spiel wird wieder von vorne anfangen. Nicht wirklich das, was man will. Und wer nicht weiß, was ein Stack ist, oder nicht bereit dazu ist sich dieses einfache Konzept anzueignen, für den ist ein Artikel wie dieser sowieso nicht geeignet. --[[Benutzer:David Scherfgen|David Scherfgen]] 15:16, 8. Nov. 2011 (CET)
  
 
== Namensgebung von Klassen und Methoden ==
 
== Namensgebung von Klassen und Methoden ==

Version vom 8. November 2011, 15:16 Uhr

Inhaltsverzeichnis

Verwendung eines Stacks

Bitte auch auf die Verwendung eines Stacks eingehen. Wenn man z.B. aus dem Spiel heraus in die Optionen geht, wird der "Optionen"-Zustand oben auf den Stack gelegt. Verlässt man das Optionsmenü wieder, wird der Zustand vom Stack entfernt und der Zustand, der darunter war, wieder aktiviert (das Spiel). --David Scherfgen 12:30, 4. Nov. 2011 (CET)

Sehr gute Idee! Ich hatte den Ansatz, es jedem State selbst entscheiden zu lassen. Dann würde ich einen Punkt für Konzepte des Zustandswechsels schreiben, der diesen Ansatz beschreibt. --Trommlbomml 10:57, 7. Nov. 2011
Man braucht dann noch zusätzliche Methoden OnGetFocus und OnLoseFocus, die aufgerufen werden, wenn der aktuelle Zustand durch einen neuen Zustand auf dem Stack "verdeckt" bzw. er wieder den Fokus bekommt, weil der Zustand oben auf dem Stack entfernt wird. --David Scherfgen 11:18, 7. Nov. 2011 (CET)
Frage ist, ob man das als Erweiterung oder Implementierungsalternative darstellt. Erweiterung würde mir persönlich besser gefallen - technische Umsetzung wird natürlich umfangreicher - Vorschläge? --Trommlbomml 12:06, 7. Nov. 2011
Ich fände es gut, wenn der Stack fester Bestandteil der hier gezeigten Implementierung ist. Die Lösung mit getNextState finde ich nicht gut, weil man doch gar nicht immer sagen kann, was der Folgezustand eines Zustands ist. Bei meinen Spielen ist es immer so, dass der Zustand einfach setState (nimmt alle Zustände vom Stack und setzt dann den neuen), pushState (legt einen Zustand auf den Stack) oder popState (nimmt den aktuellen Zustand vom Stack weg) vom StateManager aufruft.
Beispiel: das Spiel startet im Hauptmenü. Dann ist auf dem Stack der Zustand "Hauptmenü". Aus dem Hauptmenü heraus starte ich das Spiel, dieser Zustand wird oben auf den Stack gelegt. Aus dem Spiel heraus gehe ich in den Optionsbildschirm, auch der wird oben auf den Stack gelegt. Nun hat der Stack 3 Einträge. Ich verstelle etwas in den Optionen und gehe zurück ins Spiel: der Options-Zustand ruft popState auf. Der darunter liegende Zustand (das Spiel) wird wieder aktiv. Will der Spieler auch das Spiel beenden, so wird erneut popState aufgerufen, und nur noch das Hauptmenü bleibt da und wird aktiviert.
Das finde ich viel flexibler als den hier gezeigten Ansatz. Und besonders schwer zu implementieren ist es auch nicht.
--David Scherfgen 14:26, 7. Nov. 2011 (CET)
Was ich noch vergessen hatte: man kann bei setState, pushState und popState auch jeweils noch eine "Message" übergeben, die der danach aktive Zustand erhält. Wenn das Spiel den Optionsbildschirm aufruft, möchte es nachher vielleicht wissen, ob ich dort etwas geändert habe. --David Scherfgen 14:28, 7. Nov. 2011 (CET)
Und noch eine Erweiterung: jeder Zustand kann angeben, ob er beim Zeichnen "transparent" ist. Wenn das Optionsmenü beispielsweise angibt transparent zu sein, dann wird auch noch der darunter liegende Zustand gezeichnet und danach das Optionsmenü (es wird so tief in den Stack gegangen, bis ein nicht transparenter Zustand gefunden wird, und dort wird angefangen zu rendern). --David Scherfgen 14:34, 7. Nov. 2011 (CET)
Es kann ebenso sein, dass ein Spiel mit einem Intro beginnen soll (Logo vom Hersteller etc.), bevor es ins Hauptmenü geht. Genauso soll vielleicht nach dem Beenden noch Werbung für andere Spiele oder Erweiterungen gezeigt werden. Nach einer Weile der Inaktivität soll vielleicht vom Hauptmenü in einen Demo-State übergegangen werden, in dem Spielausschnitte gezeigt werden, von denen aus wieder das Hauptmenü aufgerufen wird. Die Beispiele dürften ausreichend gut verdeutlichen, dass ein State nicht genau einen Nachfolger hat. Die Optionen sollen meist sowohl aus dem Hauptmenü heraus, als auch aus dem Spiel heraus erreichbar sein. Der darauf folgende State hängt dann davon ab, welcher der vorherige war. Auch ich denke, dass ein Stack angebracht ist. --Sacaldur 14:39, 7. Nov. 2011 (CET)
Die Funktion GetNextState() ist doch flexibel. Der State kann doch unterschiedliche Folgezustände liefern - in Abhängigkeit von Update kann eine string-variable auf den Folgezustand gesetzt und bei GetNextState() geliefert werden. Trotzdem finde ich deine Lösung und Erweiterungen pragmatisch.

Warum hält man es denn nicht erst mal einfach und erweitert es dann Schritt für Schritt. Ist ja im Menü sogar so vorgesehen, dass hinterher Erweiterungen gezeigt werden. So würde ich vorschlagen, zuerst eine Version ohne Stack zu zeigen. Auch muss der Folgestate ja nicht im State selbst gesetzt sein. Man kann doch den aktuellen State selbst entscheiden lassen. Zum Beispiel könnte ein Intro-State dann Abfragen ob eine Taste gedrückt wird und in dem Fall zum Menü weiterleiten. Falls nach 5 Sekunden nichts passiert, könnte der Intro-State zu einer Demo weiterleiten. Falls hier etwas gedrückt wird gehts weiter zum Menü, ansonsten nach einer Zeit wieder zum Intro. Jeder State überlegt für sich wie er wann weiterleitet. Ein einfaches Statepattern also. Als Erweiterung kann man dann auf die Variante mit dem Stack eingehen. Klar ist dies nicht viel komplizierter, aber diejenigen die von Stacks noch nichts gehört haben schreckt es vielleicht erst einmal ab. Außerdem gibt es mit Sicherheit genug Spiele, die diese Funktionalität überhaupt nicht brauchen. So würde die die Variante mit Stack dann als Erweiterung ansehen, die dann durch die Version mit Transparenz noch weiter erweitert werden könnte. Lieber alles Schritt für Schritt erklären. --Schorsch

Das Problem ohne Stack ist, dass du dir ggf. irgendwie merken musst, woher du gekommen bist. Außerdem: Mal angenommen du gehst vom Spiel in die Optionen - dann wäre es nicht toll, wenn das Spiel "OnLeave" erhalten würde, denn eigentlich wird es ja gar nicht verlassen, sondern nur von den Optionen verdeckt. Kommst du dann wieder zurück ins Spiel, wird dort "OnEnter" aufgerufen und das Spiel wird wieder von vorne anfangen. Nicht wirklich das, was man will. Und wer nicht weiß, was ein Stack ist, oder nicht bereit dazu ist sich dieses einfache Konzept anzueignen, für den ist ein Artikel wie dieser sowieso nicht geeignet. --David Scherfgen 15:16, 8. Nov. 2011 (CET)

Namensgebung von Klassen und Methoden

Warum hast du die Methode OnInit in Initialize umbenannt? Kam bisher noch nicht vor, weil der Code fehlt, aber ich habe die Methode bewusst OnInit genannt, weil sie vom StateManager aufgerufen wird, wenn das erste Mal in den Zustand gewechselt wird und noch nicht initialisiert wurde - finde das so semantisch korrekter! --TrommlBomml 12:16, 7. Nov. 2011 (CET)

"On" klingt für mich immer nach Event, und Initialisierung ist für mich kein Event, sondern eher ein Befehl "initialisier dich!". Hat sich ja jetzt eh erledigt. --David Scherfgen 14:26, 7. Nov. 2011 (CET)

Wofür OnInit/Initialize?

Wofür gibt es die Methode OnInit bzw. jetzt Initialize? Welchen Code sollte sie ausführen, der nicht im Konstruktor ausgeführt werden kann? Und warum sollte sie erst kurz vor dem ersten Aufruf eines States aufgerufen werden und nicht nach dem Erzeugen des State-Objekts? --Sacaldur 13:29, 7. Nov. 2011 (CET)

Wenn du in den Zustand Hauptmenü bist, soll da schon dein ganzes Hauptspiel geladen werden? Das ist auch abhängig von eventuell gewählten Karten/Level, Spielfiguren... Aus diesem Grund wird erst beim ersten Wechsel geladen - quasi eine Art LazyLoading. --TrommlBomml 13:33, 7. Nov. 2011 (CET)
Ich finde auch, dass es besser wäre, wenn der Zustand selber entscheiden könnte, wann er was lädt. Also könnte er das beim ersten OnEnter machen. Initialize wäre damit überflüssig. Das ist ja sowieso fehleranfällig, weil man vergessen kann, IsInitialized auf true zu setzen. --David Scherfgen 14:18, 7. Nov. 2011 (CET)
Damit bin ich auch einverstanden. Ist schon angepasst. --TrommlBomml 14:22, 7. Nov. 2011 (CET)

Fehler in der Implementierung von StateManager

Ich habe eben für Java eine Implementierung des StateManagers hinzugefügt. Dabei ist mir aufgefallen, dass sowohl die C++, als auch die C# Implementierungen fehlerhaft sind: in beiden werden Methoden aufgerufen, die eigentlich anders heißen, wie Render statt OnRender. Ich bitte darum, dass jemand anderes, der entsprechende Mittel (Syntaxprüfung) zur Hand hat, das zu verbessern. --Sacaldur 13:51, 7. Nov. 2011 (CET)

Erst einig über Design werden, dann in allen Sprachen implementieren!

Es macht keinen Sinn, die ganze Sache direkt in 3 oder 4 Sprachen zu implementieren, wenn wir uns noch gar nicht einig darüber sind, welches Design das beste ist. Das führt ja nur dazu, dass man nachher umso mehr anpassen muss. Generell könnte man erst auch mal auf Pseudocode setzen. --David Scherfgen 14:19, 7. Nov. 2011 (CET)

Verdammt irgendwas ging da gerade schief also nochmal
Warum nimmt man für den State einen String und nicht eine Enum Variable ? Soweit ich den Code überblicke sollte es ja mit ner Enum Variable auch gehen oder ? Bei Enums sehe ich den Vorteil das man als übergabe parameter nur Vordefinierte States nehmen kann. Die States sind schnell erweiterbar falls nötig. Bei strings kann ich auch nicht state spezifisch strings übergeben, diese werden erst während der Laufzeit auf Gültigkeit überprüft. Enums werden quasi schon vom Compiler, überprüft auf Gültigkeit, falls dieser Stat nicht Existiert.
--Koschi 14:55, 7. Nov. 2011 (CET)
Grundsätzlich hast du recht. An der Stelle ist es durchaus berechtigt, wenn man es in dem Spiel direkt drin hat. Der Grund ist eigentlich nur wenn du deinen StateManager in eine extra DLL auslagerst : möchtest du für jeden neuen Zustand, den du erfindest, deine DLL neu übersetzen? Oder eine Abhängigkeit der DLL zu einem Header des Spiels haben? Durch strings kannst du in diesem Fall für jedes Spiel einen einen string als statische öffentliche Konstante der konkreten State-Klassen anlegen und diese nur verwenden. Daher sind ja auch strenge Prüfungen mit Exceptions eingebaut, so dass es auch auffällt, wenn man diesen Fehler eingebaut hat. Wenn es in dem Kontext für euch schöner ist, dann soll es meinetwegen auf Enums geändert werden! --TrommlBomml 15:34, 7. Nov. 2011 (CET)
Ich wollte nur mal den Hintergrund Erfragen weil ich persönlich viel mit Enums arbeite. Und dein Argument mit der Dll ist natürich nicht von der Hand zu weisen. --Koschi 15:58, 7. Nov. 2011 (CET)
Zu PseudoCode: Ich persönlich finde Pseudocode ungünstig. Ich lese mir sowas nie durch sondern will direkt richtigen Code sehen. In der Informatik gibt es dafür meiner Meinung nach bessere Ausdrucksmittel, wie zum Beispiel Diagramme oder schematische Darstellungen, wie bei den Stapelverarbeitungen - die ist übrigens definitiv noch verbesserungswürdig! (unsignierter Beitrag von TrommlBomml)
Dem muss ich allerdings zustimmen. Für Pseudocode gibt es keinerlei Standardisierungen, wehshalb er im Extremfall auch einfach fehlverstanden werden kann. Sofern es notwendig ist, kann statt dessen auf Struktogramme oder notfalls Programmablaufpläne zurückgegriffen werden. Um den Aufbau von Klassen und deren Beziehungen zueinander darzustellen, können Klassendiagramme verwendet werden. Es reicht meiner Meinung nach, wenn der Quellcode am Ende des Artikels aufgeführt wird. --Sacaldur 10:41, 8. Nov. 2011 (CET)

Umstrukturierung

  1. Es muss ohne Code erklärt werden, wie das Prinzip funktioniert.
  2. Der Stapel muss gleich am Anfang mit erklärt werden, bevor die State-Schnittstelle erklärt wird. Sonst versteht man gar nicht, was die einzelnen Methoden bedeuten.
  3. Code erst ganz am Ende, und auch erst dann schreiben, wenn der Artikel "stabil" ist!!!

--David Scherfgen 17:20, 7. Nov. 2011 (CET)

Das ist von der Reihenfolge besser, ich habe den Abschnitt nach vorn verschoben und die Einleitung zur Architektur etwas angepasst. Code habe ich erstmal gar nicht mehr angefasst und werde ich auch erstmal nicht - bis wir uns auf eine gute Lösung geeinigt haben.
Meine Werkzeuge
Namensräume
Varianten
Aktionen
Navigation
Werkzeuge