Reset to title/exit game

Started by
4 comments, last by Stani R 13 years, 7 months ago
What would be the best way of escaping a game's logic when implementing a reset to title/exit game function, if the game has dozens of different screens (such as an RPG; equip, status, battle, map etc)? I'm currently using C++'s exception system; when a key is pressed, my input manager throws an exception, which is caught in a loop containing the title screen and a function to start the game. Is this the best way to do it?
Advertisement
That's the worst way to do it. You're abusing exceptions. Exceptions are for when something exceptional occurs. The user pressing a key is not exceptional.

One possible way to do this is using a stack of game states or even a finite state machine. When you detect some key press, you can transition from the GAME state to the MENU state. If using a simple stack you can, for instance, start with the MENU state on the stack, then push a GAME state on it, then pop the GAME state again to return to the MENU state.
I personally prefer a stack, but for a sufficiently complex game that might not work as well as a global State* curr_state variable. The basic idea is to create a base class that declares methods for the basic things you do every frame, mainly Update() and Render(), then a subclass for each game state that implements those functions for the menu state, in-game state, pause state, etc.

The way you change which state is currently active is up to you. I like a stack because it keeps a memory of where you are in the game's screens, and lets you go back to old ones easily. This is good if you have a tree of screens and subscreens. But if you don't use your screens like that, you could just use a widely accessible variable to change what the current state is, possibly with a full-on finite state machine.

Also, IMO, it's better for interested parties to ask the input system for input, rather than for the input system to force input on the rest of the program with an exception.
Thanks; I thought there might be a better way :)

So, I've got a new plan, thanks to the advice.

A StateRenderer base class handling rendering, with derived classes for each game state (e.g. MapRenderer, MenuRenderer). Has a render() function.
A State base class handling game logic from which each game state is derived, with an update() function, and a StateRenderer* variable.
A StateManager class containing a stack of State*s, a pointer to the current State, as well as a reset flag.
A global StateManager object which is updated every frame, and updates the current state through its update() function, which in turn renders through its StateRenderer object.
At the game's start, a TitleState object is created and added to the StateManager.
When the reset key is pressed, the StateManager's reset flag is set. When the StateManager updates, if the flag is set, it clears the list of states, and re-adds a new TitleState.

Sound good? Anything need improving? Also, I have some more questions:

Should I use a singleton object rather than a global variable for the StateManager (and other potentially global variables, such as the main character's party and game settings)? I'm not very experienced with C++, and I keep hearing globals are bad :P
Is the separation of a state into a State object and a StateRenderer object, each with a pointer to the other, a good idea? It makes sense to keep the logic and graphics in separate classes.
Would it be a good idea to add functions to the base State/StateRenderer classes for things like message boxes, which act and look the same no matter what the current state is?
Yes Wichu, a GameStateManager class is a fairly common approach. On personal projects and those where I have input into the architecture I like to have "BeginState" and "EndState" functions in the state manager. So for example, if you quit from single player game to main menu, EndStateSinglePlayer() would be fired and cleanup and do last minute player saves, then BeginStateMainMenu() would unload all content and load the main menu screen. However you do it, you are going to want a clean way to organize all actions that must occur on transitions between states.

Making the state manager a global is not necessarily a bad thing. It makes it easily accessible from anywhere. I don't see a real need to make it a singleton, unless you somehow don't trust yourself to not randomly declare another state manger for no apparent reason somewhere else in your code...
Quote:Original post by Wichu
Should I use a singleton object rather than a global variable for the StateManager (and other potentially global variables, such as the main character's party and game settings)? I'm not very experienced with C++, and I keep hearing globals are bad :P


Singletons are globals too, they just have syntactic sugar that makes inexperienced people think that they are doing something good while they are actually making their situation worse. Singletons have exactly the same problems as globals, for instance they make it really easy to produce spaghetti code and are for the most part not thread-safe. They also unnecessarily enforce a constraint that there should only be one instance of some object - if you only need one, only make one. Look for "singleton" on the search engine of this forum for a more in-depth discussion, but generally stay away from singletons and globals as much as possible. There are different alternative philosophies, but the one I prefer most is Dependency Injection because it makes dependencies very explicit.

In general if you have global state you are doing something wrong. In reality you usually do not need any of the things you think you need to be global, you are just simply not yet clear about where they will be used so your gut answer is "everywhere". That's almost never the case.

This topic is closed to new replies.

Advertisement