30
\$\begingroup\$

As far as I can tell, most games have some sort of "game state system" which switches between the different game states; these might be things like "Intro", "MainMenu", "CharacterSelect", "Loading", and "Game".

On the one hand, it totally makes sense to separate these into a state system. After all, they are disparate and would otherwise need to be in a large switch statement, which is obviously messy; and they certainly are well represented by a state system. But at the same time, I look at the "Game" state and wonder if there's something wrong about this state system approach. Because it's like the elephant in the room; it's HUGE and obvious but nobody questions the game state system approach.

It seems silly to me that "Game" is put on the same level as "Main Menu". Yet there isn't a way to break up the "Game" state.

Is a game state system the best way to go? Is there some different, better technique to managing, well, the "game state"? Is it okay to have an intro state which draws a movie and listens for enter, and then a loading state which loops on the resource manager, and then the game state which does practically everything? Doesn't this seem sort of unbalanced to you, too? Am I missing something?

\$\endgroup\$

11 Answers 11

31
\$\begingroup\$

I think you're just arguing semantics here. It's called Game State because it behaves like a Finite State Machine, with a finite number of states and transitions between them. The 'Game' in 'Game State System' refers to the overall system, with 'Loading', 'MainMenu' etc being states of the game. These could easily be called 'scenes' or 'screens' or 'levels'. Its just semantics.

I'm not sure that a strict FSM applies anymore. In my implementations I call states 'Screens' and allow them to be stackable - ie. screens can be drawn on top of other screens, controlling whether or not screens below them are updated or drawn. In this way, I can have multiple screens active at the same time with self-contained logic and code specific to that screen, without having to worry about any other screen.

A Pause screen, for example, could be opened on top of my main gameplay screen that disallows updates, but allows drawing below itself. A character inventory screen could allow both drawing and updates - so the game keeps playing while you're working in your inventory.

\$\endgroup\$
3
  • \$\begingroup\$ this is exactly how it should be done. Screens should be able to contain multiple other screens in a tree-like architecture. So your program contains a game screen, which contains a pause-menu screen, which contains an audio settings screen and a game settings screen. etc \$\endgroup\$
    – Iain
    Aug 9, 2010 at 8:54
  • 1
    \$\begingroup\$ I would love to see example source code for this! (Preferrably in C++/C#/Java) \$\endgroup\$
    – Zolomon
    Aug 31, 2010 at 6:18
  • 1
    \$\begingroup\$ Unfortunately, I only have production code at the moment, but there is a similar concept in the XNA Game State sample: creators.xna.com/en-GB/samples/gamestatemanagement \$\endgroup\$
    – DrDeth
    Sep 21, 2010 at 22:22
8
\$\begingroup\$

Sure the Game state would be huge, but there's no reason that the Game state itself can't contain a state machine to manage its data. Hierarchical state machines are useful.

\$\endgroup\$
4
\$\begingroup\$

I always like to the think of each "state" as a "scene". So the opening video is a scene, just a static one. The credits are a scene. The menu is a scene. The only difference between them all is the level of interactivity and game logic.

\$\endgroup\$
3
\$\begingroup\$

I have problems with that too, actually.

Let's say you have a Game.

Instead of making 'Game' a state like 'Loading', 'Main Menu', etc. - IMO it's better to let Game have several states:

"Loading" - "showing menu" - "paused", etc.

The Game is still running, but when it shows the main menu it would be in 'show menu' mode.

And when Game is not in any particular state, it's just running.

It makes much more sense, at least to me. :)

\$\endgroup\$
1
  • \$\begingroup\$ I agree. Nobody wants to exit the Game-State just to enter the Pause-State. On the other hand: It's still a state system.. just nested :) \$\endgroup\$
    – bummzack
    Aug 9, 2010 at 8:23
2
\$\begingroup\$

An online program (in the traditional meaning of online, ie. continually running and responding to input, rather than meaning connected to the internet) typically consists of 3 things:

  • input gathering and handling
  • updating of logic
  • output

Generally speaking, these 3 are related and change at the same time. For example, when displaying a splash screen you might map all your keys to a 'close screen' command and the update may be fading a graphic in slowly with the output just showing that graphic. But when playing a game the keys may all map to different commands and the update is changing properties of many in-game objects.

When you view it this way, it makes sense to separate an Intro from Character Creation and from the Game proper: each has its own set of input, update, and output rules. They're almost like self-contained programs that happen to share some data and library code. And, with this in mind, it usually makes sense to have just one Game state, since the gameplay is fairly homogeneous throughout.

Of course, if you do actually have separate types of gameplay (eg. an RPG example - World Map, Town Map, Cutscene, Combat), with differing input, updates, and output, there's no reason you couldn't have multiple states there too instead of just 1 Game state. But it depends on your game.

\$\endgroup\$
1
\$\begingroup\$

I look at it the other way. 'Menu', 'HighScores', "credits" or whathaveyou, could be considered as just another level, and then that state isn't necessarily lighter than your 'game' state (the game state just happens to have more entities in general, and different ones, but in the end it's just another level where the entities happen to show more predicatble behaviour and the 'maps' are generally less intricate).
Making that switch in your thinking definitely pulls you out of the "boring menu" syndrome.

\$\endgroup\$
1
  • \$\begingroup\$ I was going to say the same... All my menus, screens, whatever, are just another level. \$\endgroup\$
    – speeder
    Aug 9, 2010 at 3:35
1
\$\begingroup\$

In my game, I have:

Execution Manager, which initalizes the application (game), loads resources, releases resources on application exit, etc. It initalizes Application Engine, GameViewEngine, GameLogicEngine.

Game State Manager, which resides in the GameLogicEngine, and is responsible for controlling the things related to game main loop: collision detection, physics calculation, keyboard reading, math operations, etc...

Initially, I tended to have only one Game State Manager which was part of my GameLogicEngine. However, I had some difficulties with controll over the intialization of main subsystems (GameLogic, ApplicationEngine, ...). It could have been done, but it was more messy, imo.

Now things look more transparent to me, and I am happy with the design.

\$\endgroup\$
0
\$\begingroup\$

Rename the 'Game' state to something like 'Gameplay'. Then your logic seems better; You stop playing to go to th menu : you exit the Gameplay state to go to the MainMenu state.

Also, I think things like pause, which would require the game to be in the same state as when you paused the game, should not be separate states. Child states and nesting, perhaps? The Gameplay has-a pause menu.

\$\endgroup\$
0
\$\begingroup\$

I think that there is a good method called a game-state stack. I haven't seen any papers or articles about it but it's been spreading a little bit by voice. Essentially the topmost game-state on the stack is called first and gets to do whatever it wants to with input/rendering etc. The topmost game-state is the only one allowed to push or pop states.

In my engine, game-states are actually just lists of game entities. I then have entities that work as menus. My menu-states either pause the game (by not updating the next item on the stack) but let the other state(s) push their models to the renderer so that my pause-menu (which doesn't cover the entire screen) still has the game rendering in the back.

I hope that gives an idea of a little bit different system that isn't based on a state-machine.

\$\endgroup\$
0
\$\begingroup\$

Is it okay to have an intro state which draws a movie and listens for enter, and then a loading state which loops on the resource manager, and then the game state which does practically everything? Doesn't this seem sort of unbalanced to you, too? Am I missing something?

This is perfectly fine. Or at least, it is an improvement over "having a big ugly switch depending on the state the game it is".

I'd like to point out that in most games you will already need a finite state machine of sorts in order to deal with simple entity AI. The typical example are enemies that are on Iddle state, Attacking or Dieing.

If you have a sufficiently abstracted Finite State Machine, then you can re-use it for both the Game object and your AI; suddenly you are not "investing" lots of effort on the Game state - instead you are reusing code that you used anyway.

Shameless self-plug ensues: I've implemented such a Finite State Machine on my Lua game library, MiddleClass (concretely, the add-on called MindState). Here's how you do a Game State thing with it.

\$\endgroup\$
0
\$\begingroup\$

A different approach to this is to use a concept from the functional programming world called a Discriminated Union. Whilst these are typically found in FP languages, you can emulate them using classes.

Basically, a Discriminated Union is a type that is always one of n cases, and the data stored can vary with each case.

For example:

type GameState =
  | Menu of MenuState
  | Playing of SimulationState

Here, our GameState type can be either Menu or Playing. If it is Menu, then it will contain a MenuState object. If it is Playing, then it will contain a SimulationState object.

To update, we would match on the state, and call a different function accordingly:

let update gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> updateMenu gameTime menuState
    | Playing simulationState -> updateSimulation gameTime simulationState

  // Mutate the current state
  gameState <- nextState

And similarly for rendering:

let render gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> renderMenu menuState
    | Playing simulationState -> renderSimulation simulationState

One advantage of this approach is that you can handle things across states (such as resources) more easily without globals or passing around "service" objects.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .