How do people typically handle game states?

Started by
7 comments, last by tonyg 13 years, 1 month ago
So I have a basic engine with a main loop that looks something like this:
while(!quit)
{
handle();
update();
render();
}

But how do I handle the various unique game states? I.E.: Say I am at the menu... and I click "start game." Now all the game resources have to be loaded and the handle(), update(), and render() functions must change in behavior drastically. Is there a sensible and manageable way to do this for a relatively medium to large scale project that can be conveyed in a reply? Thanks.
Advertisement
A common approach is to move the handle/update and render functions in their state instances.

Imagine an abstract base class for a gamestate. Derive states for game, menu, editor, etc. and store the active states in the main app. The main loop simply calls the methods of the current state.

In my gamecode I actually have a stack of active states. This allows for overlayed states, for example a submenu displayed over the game.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>


So I have a basic engine with a main loop that looks something like this:
while(!quit)
{
handle();
update();
render();
}

But how do I handle the various unique game states? I.E.: Say I am at the menu... and I click "start game." Now all the game resources have to be loaded and the handle(), update(), and render() functions must change in behavior drastically. Is there a sensible and manageable way to do this for a relatively medium to large scale project that can be conveyed in a reply? Thanks.

Even a large scale game generally won't have very many "main states". There's the main menus, the in-game, maybe a loading/cutscene state, the pause menu.... maybe a couple of others. The different states tend to act very differently from each other, and transitions between them are usually not very similar to each other. The heterogeneity and small number of states makes it a good idea NOT to go with a regimented, OOP-ized "state machine" approach, but rather just a few switch statements. Further refinements of those states, which also don't tend to resemble each other, should be handled on their own merits.

In particular, beware of shoving all the "non-main states" together into the same formalism, with the CONTROLS_MENU and AUDIO_MENU states rubbing elbows with the GAME_PAUSED state and the IN_BOSS_BATTLE state. That sort of a Procrustean bed serves no purpose except to give an overengineered state machine module a reason to exist.
I think I explored this about a year ago, specifically the stack-based system where states were derived from an abstract class. What I decided based on experience and advice given to me is just as Sneftel has said, it's really just overengineering, and for what, a stack based system that really doesn't handle too much in a small project and one that doesn't accurately represent 'states'. In a stack based system, if I push a Main Menu and then a Play Game from the Main Menu then I still have a menu on the stack that I will never be able to get rid of (Main Menu). If I did remove the menu before entering the Play Game State, then it's a stack behaving like a queue, what's the point?

Basically, you're just better off using an enum and a switch statement and doing 99% of the functionality with 5% of the code. A stack may be a better choice for a pause menu system.. but if all you have in your pause menu is a resume/quit option, then once again, you will get the same functionality by just making a bool isPaused, and it's much easier.
I have been thinking about this for a while. For the current project I'm involved with, we are using switch statements, which works quite well for the most part. Except dealing with saving and restoring states is an issue which can get messy.
Latest project: Sideways Racing on the iPad

Except dealing with saving and restoring states is an issue which can get messy.



When would you ever need to restore a state, out of curiosity? If it's something like a pause menu could you not just halt the update loop with a bool pause value and fade the game to the background?


I think I explored this about a year ago, specifically the stack-based system where states were derived from an abstract class. What I decided based on experience and advice given to me is just as Sneftel has said, it's really just overengineering, and for what, a stack based system that really doesn't handle too much in a small project and one that doesn't accurately represent 'states'. In a stack based system, if I push a Main Menu and then a Play Game from the Main Menu then I still have a menu on the stack that I will never be able to get rid of (Main Menu). If I did remove the menu before entering the Play Game State, then it's a stack behaving like a queue, what's the point?


Hold on; you're getting two totally different things mixed up with each other here. Making game states that are derived from an abstract class has nothing to do with managing a stack of those states. There are plenty of other ways to use the state objects, and having them can be very useful. It really doesn't require that much extra code (even less so in friendlier languages that don't involve so much boilerplate just to create classes).
When would you ever need to restore a state, out of curiosity? If it's something like a pause menu could you not just halt the update loop with a bool pause value and fade the game to the background?


What we've got at the moment is the in-game graphics kept on screen while the menu is displayed. Essentially we have slide-menu that animates into view. While the slide menu is animating, we need to keep the game stuff rendering and updating. Only when the menu is fully visible we pause the game. Even then, the menu has animated features, which requires the occasional update for everything. To accommodate most of that, we have separate state enums that represent different phases of the menu animation. Naturally this incurs a lot of redundant code, as most the update logic in each state is simiar, but not quite the same. Plus we have also a bunch of state flags to maintain on top. Doing this in C doesn't help either! Admittedly, the whole thing could have been better implemented from the get-go, but some game design decisions were introduced later in the project.

Moral of the story: If you go for a big state machine system, plan and set design decisions into stone as early as possible.

And draw nice flow charts.
Latest project: Sideways Racing on the iPad
Sorry if somebody has already mentioned it but does this help :
Managing Game Stats

This topic is closed to new replies.

Advertisement