Gamestates
-
Der Stack hat auch den Vorteil dass du vom Hauptmenü aus ins Spiel kannst und vom Spiel wieder ins Hauptmenü und dort wieder ein Spiel starten ...

-
Krux schrieb:
Das A und O der objektorientierten Programmierung ist das verstecken von Informationen, was bedeutet, dass in der Main Funktion fast nichts drin stehen sollte, und alles auf Funktionen ausgelagert wird. Zudem sollte jedes Modul auch jederzeit austauschbar sein durch ein anderes.
und genau diese prinzipien will ich mir jetzt aneignen. nur ich bin noch nicht so schrecklich weit was eigene projekte angeht

genau genommen wäre das dann sogar mein erstes von vorne bis hinten durchgecodete spiel

deshalb würde ich jetzt erstmal das konzept von krux vorziehen weils für den anfang wahrscheinlich einfacher ist. nur bin mir noch ziemlich unsicher, was ich in welche funktion/klasse schreiben muss. gibts vielleicht irgendwo mal ein tutorial wo man wenigstens mal den ansatz von kapselung erkennen kann? ^^
-
Hier ein Tutorial zum Stack-Ansatz:
http://gamedevgeek.com/tutorials/managing-game-states-in-c/
-
In vielen PC spielen unterscheidet man zwischen inGame menü und Hauptmenü, was auch sinn macht, und das schafft der zwitchblock genauso, wie die Abstakte Klasse mit dem Gamestack. Wer will schon aus einem während des laufenden spiels ins Haupmenü, um von dort ein neues zu starten, ohne das alte zu beenden?
-
Krux schrieb:
In vielen PC spielen unterscheidet man zwischen inGame menü und Hauptmenü, was auch sinn macht, und das schafft der zwitchblock genauso, wie die Abstakte Klasse mit dem Gamestack. Wer will schon aus einem während des laufenden spiels ins Haupmenü, um von dort ein neues zu starten, ohne das alte zu beenden?
Normalerweise wird bei dem Vorgehen wo es ein Hauptmenü gibt dann ein "zurück zum spiel" eingeblendet und bei "neues spiel starten" gefragt ob man das alte wirklich beenden will. Oder hast du schonmal erlebt, dass ein Spiel tatsächlich ein neues startet wo eine alte Instanz noch läuft?
-
lolz schrieb:
Krux schrieb:
In vielen PC spielen unterscheidet man zwischen inGame menü und Hauptmenü, was auch sinn macht, und das schafft der zwitchblock genauso, wie die Abstakte Klasse mit dem Gamestack. Wer will schon aus einem während des laufenden spiels ins Haupmenü, um von dort ein neues zu starten, ohne das alte zu beenden?
Normalerweise wird bei dem Vorgehen wo es ein Hauptmenü gibt dann ein "zurück zum spiel" eingeblendet und bei "neues spiel starten" gefragt ob man das alte wirklich beenden will. Oder hast du schonmal erlebt, dass ein Spiel tatsächlich ein neues startet wo eine alte Instanz noch läuft?
Nö, aber genau das habe ich verstanden, als die Gamestates erklärt wurden.
Macht man das mit der Abstrakten klasse muss man eben genau dies beachten, ob ein spiel bereits läuft, oder nicht, und dann dementsprechend dann die einträge verändern, macht man es auf meine Weise mit dem ingame und Hauptmenü, muss man auf sowas nicht achten, weil es zwei ganz verschiedene Menüs sind, die Designmäßig auch anders aussehen können. Machen kann mans wie mans will, ich find nur meine Lösung übersichtlicher bzw einfacher, jedoch keineswegs in irgendeiner weise schlechter, aber das kann auch daran liegen, dass ich damit schon gearbeitet habe, und mit gamestates nicht. Ja und wie ihr sicher schon mitbekommen habt, ich mag init-Funktionen nicht.PS: Ingame und Hauptmenü unterscheiden sich oft in viel mehr dingen, als blos den Spiel-Starten-Knopf
-
Du musst aber zugeben, dass das keine sehr elegante Lösung ist. Selbst in C würde man doch eher Funktionszeiger nehmen als einen switch-case-Block.
Und wenn du beispielsweise eine Engine schreiben willst, die die Verwaltung der Spielzustände übernimmt, dann wäre das mit deinem Ansatz nur schwer möglich, da du bestehenden Code in der Engine verändern müsstest, um z.B. neue Zustände einzubauen, und das ist nun wirklich nicht schön.
Zudem gibt es bei dir mehrere geschachtelte Hauptschleifen (einmal eine im Hauptmenü, und dann z.B. nochmal eine im Spiel), was eine Menge redundanten Code mit sich ziehen wird - beispielsweise Zeitmessungen, um unabhängig von der Framerate zu bleiben oder andere Dinge, die in jedem Frame erledigt werden müssen.Der Ansatz mit einer abstrakten Klasse und einer Implementierung je Game-State, und zur Verwaltung ein endlicher Automat oder eben ein Kellerautomat (Stack-Automat), ist auf jeden Fall am flexibelsten (und braucht auch keine "init-Funktionen"!). Ich denke, wenn man schon C++ nutzt, dann sollte man hier auf den objektorientierten Ansatz nicht verzichten.
-
hm also ich will hier niemanden beleidigen indem ich seine lösung nicht nehme, ich nehm glaub ich am besten erstmal das einfachste. danach bin ich gern bereit über optimierungen zu reden ^^
-
Hi,
ich versuche auch gerade diese Gamestates mit Stack umzusetzen, was ganz gut in dem Link oben beschrieben ist. Allerdings haben die einzelnen State-Objekte eine Haken. Wer ist das Löschen der States zuständig?
Im Artikel wird empfohlen, die States als Singletons zu implmentieren, aber das scheint mir unflexibel zu sein. Wenn ich beispielsweise einen Spielstate hab, der den Zustand eines Levels darstellt und ich von dort aus in ein "Unterlevel" wechseln will, dann leg ich auf den Stack einfach einen neuen Spielstate drauf. Mit Singleton geht das aber nicht. Da muss ich mir den alten State speichern, dann überschreiben und am Ende des Sublevels alles wieder zurüchschreiben.
Alt Alternative mir bisher nur ein globaler State-Container eingefallen ..
Wie macht ihr das?Grüße,
don_basto.
-
ich hab das bei mir in der art von webpages realisiert. wenn man zu einem anderen bereich moechte, dann gibt es eine verlinkung dafuer. jede "page" hat ein lifecycle, sie wird initialisiert, danach laeuft sie und am ende, wird sie terminiert bevor die naechste "page" geladen wird.
in pseudocode etwa
autoptr<Module> Module; std::string ModuleName("Index"); std::string LastModuleName; while(ModuleName!="") { if(ModuleName!=LastModuleName) { Module.Release(); Module.Load(ModuleName); Module.Init(); } LastModuleName = ModuleName; ModuleName = Module.Run();//placebo fuer rendering,update,logic,input etc. was man sonst hier machen wuerde... } Module.Release();parameter uebergabe usw. laeuft dabei mittels einer statemaschine ala
std::mapstd::string,std::string g_DB;das schoene ist, dass ich zum ablegen eines savegames nur die g_DB speichern muss. da ich ja zum zurueckspringen aus dem savemenue wieder den alten zustand herstellen muss, muss ich mir eh alles wichtige dort ablegen und genau die selben daten kann ich dann nach dem laden haben.
bei mir ist auch jedes fenster/dialog eines menues eine 'page', somit ist das mainmenue eine ansammlung von 'pages'.
rapso->greets();