2
\$\begingroup\$

A game is a set of Game States.

Each Game State contains game objects, may be list, may be scene graph or any other data structure.

We can use Game States as Game Locations, too.

How do you share data between Game States, for example, hero and his/her inventory when it moves from one location to another?

It looks like Composite (hierarchical) Game State is a good idea. For example,

GameState MainMenu
GameState LoadLevel
GameState Gameplay - contains inner states
    GameState Location1
    GameState Location2
    GameState Location3
    GameState MiniGame1 - contains inner states
        GameState LocationInMiniGame1
        GameState LocationInMiniGame2

So we can hold shared data (hero, inventory) in Gameplay object. But this approach does not look very correct and flexible. If some objects are outside scene graph (ie in the parent Game State), how would you include it in the scene graph? Via special node type that mounts different scene graphs or scene graph branches together?

If we have stack of active Game States, and each state can contain inner state machine, and scene graphs of different Game States can be mounted into one giant graph, it can become very complex system that is hard to debug.

Very interesting to read your suggestions. How do you organize game data between Game States in your real applications?

(For editors: possible additional tags: OOP, game-state.)

\$\endgroup\$

3 Answers 3

6
\$\begingroup\$

The concept of state stacks is very valuable and very useful in games. One particular game in my memory had the major states of "main menu", "playing a movie", "in game", and "in-game menu", with a centralized place that handled transitioning between these things. It was great because you could push a ton of crap at once and end up where you wanted to be without guessing. E.g. at startup "main menu" is pushed, then "movie" (gamelogo) then another "movie" (dev logo) then a third movie (pub logo).

Then the in-game had a ton of state, and that state was per-level. In this case it didn't make sense to make it a stack, since only one could be active at a time and the endlevel code would take care of transitioning to the next level (after pushing the load/save UI which in this case was part of the main menu).

Each level will likely have a ton of "areas" or sublevels or whatever. There is stuff that exists only in an area (e.g. the monsters), but there is the stuff that transcends the sublevels and is more appropriately "owned" by the level itself or even the in-game state "object". (The game I'm recalling had different player "costumes" in different levels, so it made sense to attach that to the level. Other games might just load a single player model and use it for the life of the in-game state.)

Some states do have sub-states though. These aren't polluting the "main" state stack, these are internal state stacks. E.g. the in-game menu will have a page stack like Ricket discusses so that "back" works uniformly. The memory card handling may be another separate stack too since it runs asynchronous to the rest of the UI.

In short, put data where it makes the most sense to you, and don't hesitate to move it if another home becomes preferable.

\$\endgroup\$
9
\$\begingroup\$

My suggestion is to not have game states like this whatsoever. Most of your essential game objects exist across and outside of all the states (eg. renderer, resource loading, input, networking, audio), and a massive amount of the rest span multiple states (eg. players, some NPCs, certain resources).

On top of that, the stack system doesn't seem to work well in practice. What if I want to bring up an options menu from within the mini-game - how is that going to differ from bringing it up from the main menu? What if I can quit the whole game from within the mini-game?

I'd ask, what value does this big state system give you? If you need to know what location you're in, store a location object or variable. If you're on the main menu, your GUI object will have a menu panel up; otherwise, it won't. Maybe there's an argument for pushing a new state when you enter a mini-game or cut-scene but I don't think I'd even do it then.

So my answer to "how do you share data between same States" is to not have game states at all.

\$\endgroup\$
16
  • \$\begingroup\$ I can't downvote Ricket's longwinded defense of global variables or upvote this answer enough. \$\endgroup\$
    – user744
    Sep 28, 2010 at 15:02
  • 1
    \$\begingroup\$ @Pavel: you can do that sort of thing with a single game loop, an 'is_paused' flag, and a GUI. eg. bind the Escape key to { pauseGame(); showMenu(); } and when you close the menu, call { unpauseGame(); hideMenu(); } There are no more globals needed in this case than the state stack case - you essentially just have 1 game state instead of several. \$\endgroup\$
    – Kylotan
    Sep 28, 2010 at 15:50
  • 1
    \$\begingroup\$ @Kylotan: How do you implement mini-games without states? Different modes of gameplay (exploring, combat etc.)? If you have many hierarchical submenus, it is not enough to have a showMenu() function. May be I'm wrong, but I think your code will become spaghetti code, if you do not use Game States in these cases. \$\endgroup\$
    – topright
    Sep 28, 2010 at 19:13
  • 1
    \$\begingroup\$ Wow. The games I've worked on with state stacks were the ones with the fewest (i.e. zero) state transition bugs. I'm not sure how Joe W thinks that this post isn't about global variables, either. \$\endgroup\$ Sep 28, 2010 at 21:53
  • 1
    \$\begingroup\$ Game states are a logical refactoring of this answer's proposed "big messy loop with lots of flags and switch statements". I'd like to know some concrete examples of games that shove everything into a single game loop method with no concept of state objects. And as for "global variables", there's no difference, can't you see? - my suggestion is to have some variables shared by several states; this answer suggests all the states together in one loop, with shared variables. Absolutely no difference right? Or you can use Singletons (AKA global variables). \$\endgroup\$
    – Ricket
    Sep 30, 2010 at 20:46
-1
\$\begingroup\$

I started learning programming from web development. My first steps were opening notepad, writing some HTML, saving it, and opening it in a browser. Then I wrote another HTML file and saved it. And then I made a link. Suddenly I had two pages which I could go back and forth between.

Then I got into PHP; I could handle user input! I could even save data about an user. I used cookies or the session to save data about the user between pages.

Now just a few months ago, as I was thinking and wondering the same question as you, I realized game states are like PHP pages. They're very discrete, each one being a different view of your application (game, in this case), but they need some shared data. They need session data.

Well, in PHP, to store something in the session you just use $_SESSION['variablename']='value';. Then you can later retrieve that data, from any PHP page visited by the same user in the same session, by referring to $_SESSION['variablename'];. Essentially, it's a global array, and in PHP you can easily add values to an array so it's essentially equivalent to a Map.

So if you want to go this route, then add a "global" Map which acts as your "session" data. This will hold all of the data that needs to be shared between game states. Or simply make it a "global" object and add all the variables you need; this is entirely up to you, based on your needs. (obviously an object will get much better performance than a Map) - when I say "global", I mean make it available to all of your game states. You shouldn't make it available to any other objects which don't need it. This can be done, for example, by a variable inside the gamestate namespace, or a package-private Singleton in a language like Java.

Note this is only one way to do it. I really kind of like the way you want to attach the data to the parent Gameplay object; but in my state system I didn't really account for sub-states so I was just thinking of the PHP way.

\$\endgroup\$
5
  • \$\begingroup\$ Interesting answer, thank you. I have PHP background, too, so you just hit the bull's eye. :) \$\endgroup\$
    – topright
    Sep 28, 2010 at 14:07
  • \$\begingroup\$ Globally available, globally mutable state is almost always the wrong solution. \$\endgroup\$ Sep 30, 2010 at 19:11
  • \$\begingroup\$ Okay then let's say you write a multiplayer game. The main menu establishes a network connection, stored in some sort of network connection variable, and then starts the game state. How does the game state get access to that network connection without shared data? \$\endgroup\$
    – Ricket
    Sep 30, 2010 at 20:36
  • 2
    \$\begingroup\$ Shared data does not mean global data. Pass what you need, don't pass what you don't, and don't access anything you aren't passed. (That's the ideal at least.) \$\endgroup\$
    – user744
    Oct 1, 2010 at 0:07
  • \$\begingroup\$ Static variables in the local compilation unit or package-private singletons in Java are still "globals" when it comes to reasoning about program execution. You're accessing stuff you aren't passed; you're forced to reason about a much larger part of the program. \$\endgroup\$
    – user744
    Oct 1, 2010 at 15:26

You must log in to answer this question.

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