Hey,
ich versuch mal, meinen Gedankengang bei dem Ganzen zu zeigen.
Also zunächst:
Was ist ein GameState?
Ein GameState repräsentiert nicht nur irgendetwas, im Prinzip sagt der GameState aus, wo man sich gerade im Programm befindet:
Intro, Menü, spezifisches Menü oder aber eben das eigentliche Spiel, oder ein Dialog oder sonstwas.
Ein GameState hat also das Grundlegende gemeinsam: ein GameState muss Stati gewisser Variablen updaten können, davor gewisse Initialisierungen treffen können, außerdem das ganze auch noch zeichnen können sowie natürlich hinteher auch wieder aufräumen.
Eine abstrakte Klasse könnte also so aussehen:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
|
class cGameState
{
public:
virtual ~cGameState();
virtual void StartState() = 0; // Initialisierungen etc.
virtual void CloseState() = 0; // Aufräumen!
virtual void Update(...) = 0; // Hier findet die Logik statt. Könnte man auch Think() oder so nennen, wies manchmal üblich ist
virtual void Render(...) = 0; // Und hier wird alles gezeichnet.
};
|
Mit dieser Klasse haben wir die Basis geschaffen. Was jetzt noch fehlt ist eine Klasse, die die GameStates bearbeitet.
Am besten ist es imho folgendermaßen - so hast dus denk ich ma schon, wills trotzdem nur noch mal kurz klären:
Eine Klasse beinhaltet einen vector von GameStates und ruft dann eben immer die Update() und Render() Funktion des zuletzt hinzugefügten GameStates auf.
Dann fehlen eigentlich nur noch entsprechende Funktionen zum Leeren und Füllen des vectors und dann wars das.
Das könnte z.B. abgespeckt so aussehen:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class cStateManager
{
public:
cStateManager();
~cStateManager();
void PushState(cGameState* pState); // Einzelnen State hinzufügen
cGameState* PopState(); // Neuesten State entfernen
void Update(); // Alle Update Funktionen aufrufen
void Render(); // Alle Render Funktionen aufufen
};
// blabla
|
etc etc etc, ich denke du weißt genau wie ich das meine
.
Jetzt kommt der Clou:
Jeder State ruft den nächsten auf.
Wenn der IntroState bspw, der abgeleitet von cGameState ist, nun Text enthält und Bilder zum Rendern etc, kannst du einfach am Ende des States dem statemanager sagen, dass er einen neuen menustate hinzufügen soll z.B.
Du musst nur dafür sorgen, dass der StateManager von überall aus ansprechbar ist. Ich regel das ganz fies darüber, dass der statemanager nach dem singleton-pattern aufgebaut ist und er auch das Window handlet, so ist in jedem State alles nötig ansprechbar.
Ich verfahre mit diesem System schon eine ganze Weile und ich denke nicht, dass es das beste ist, aber es ist sehr leicht überall umzusetzen(da ich jetzt mehrere Libs etc getestet hab) und birgt für mich auch keine offensichtlichen Probleme.
Man kann da sicher noch modifizieren und optimieren, das werde ich wohl auch tun, aber für den Anfang ist es für mich DIE Lösung