help with game states

Started by
9 comments, last by Kimmi 15 years ago
I am messing around with game states in my game. Currently i have it working like below

class GameState
{
  virtual void init();
  virtual void deinit();
  virtual void draw();
  virtual void update();
};
then for each of my game states i derive a class from this base class. Then when i want to transition to a new game state...a push this new game state onto a stack. then in each loop of my game i do

game_state_stack.get_last_state().update();
game_state_stack.get_last_state().draw();
the problem i have is this. Lets say i am in a game state of GAME_STATE_PLAYING and i want to open an options screen that overlaps on the playing screen (and pauses the playing screen). So i want to push a new state called GAME_STATE_OPTIONS onto the stack. This is working fine except for the fact that i want to options screen to overlay (right work) on top of the playing screen. This would require me to redraw not just the top state in the stack but some or all of the ones below it. so then i think i will just loop through the stack and draw ALL states but only update the top state in the stack. This works but seems too much unnessary drawing. Because if i start the game with the MAIN_MENU state then user clicks on start game so we push on the GAME_STATE_PLAYING then the user opens options so we push on GAME_STATE_OPTIONS. So if we draw the whole stack then we are unneccessarily (sp?) drawing the main menu. What should I do ?
Advertisement
Quote:Original post by ncsu121978
What should I do ?


You could provide a virtual bool should_render_parent() const method so each state can decide whether the state beneath it should be rendered prior to rendering itself.

Whole-screen states like start screen mode or game mode would return false, options menu would return true, other modes could return different values depending on context etc?

Personally I've given up using a stack of game states - unless you are writing something like an RPG with heavily nested menus or screens, I think it is overkill. I use a similar interface to yours but just have a single std::auto_ptr<BaseMode> that contains a pointer to the current mode. I just switch between modes in response to game events, so when the game is running, the start screen and all its resources are automatically destroyed etc. Assigning a new start screen pointer to the std::auto_ptr automatically destroys all the game state resources etc. Things like options menus are handled as a special case.

Depends on the application though.
actuaqlly, i dont like this option of leaving it up to the state to draw the parent...
i think, its better information hiding, if every state has something like "doPassiveUpdate()" where in your example it can draw itself but doesnt react to input and after that, the option screen is to be drawn
I think an enum of flags better represents game states than a stack. Then your state could be GS_PLAYING | GS_PAUSED and you can do the right thing easily eg:

if ((state & GS_PLAYING) == GS_PLAYING) {    /* draw game world */    if ((state & GS_PAUSED) == GS_PAUSED) {        /* draw pause menu overlay */    } else {        /* not paused, update game world */    }}


Aren't ifs and switches so much more flexible than class hierarchies?
Anthony Umfer
the problem i am trying to avoid with the whole enum thing is HUGE if/else code blocks or HUGE switch statements to deal with all the game states.

the things i am working on now are sub-states of one of the main game states. example: i have a state GAME_PLAYING to represent the main playing portion of the game. The game is turn based to within this GAME_PLAYING state there are several sub-states such as WAITING_TO_PICK_UNIT, PICK_UNIT_ACTION, CHOOSE_TARGET, ect....

i am thinking on if i should use a switch/if/else for these of just subclass them as well and push them on the atack.
I use a similar state system and just have a flag in every state whether they desire to be rendered still. When I run through my state stack I check the flag before calling the draw() function. This way each state can control drawing functionality individually (which is required, as sometimes you want everything drawn and other times you only need the top state drawn).
Why not make an visible flag in the state, and an IsVisible accessor. Always loop through all states, and only render the ones that are visible. The one at the top of the stack will have the focus, but the rest will render afterwords, painter's style.
It strikes me that if two of your game-states need to share state (game rendering) then, by definition, they're not separate states in the first place.
I was using state managers for rendering in two ways- one is to assign a single rendering device to the state manager (this device depends on the API you're using), and the other option is to let each state load its own device. The first option is the one you seem to be using- letting the state manager prepare the rendering for each frame and then complete it after it went through all the states in the stack.

My suggestion is to add a new function to your GameState class: pause. Because it sounds like every single state is continuously being "active" despite being buried somewhere in the stack, and seems like a waste of CPU activity.

Immediately before you push a new state onto the stack, call the last state's pause() function. By default, a pause function could be empty- no updating, no rendering, no taking input. Almost what you'd expect from a paused status. But you can also make the paused state do something, in this case continue to render things in the background by using draw() inside pause() and, optionally add other functions.

Removing the top state from the stack should be followed by calling update() again from last state, and then you're back in your previous state's update and draw loop again.
Electronic Meteor - My experiences with XNA and game development
you can do as I do and keep a flag for each state IsSeeThrough. You dont even have to loop through your states that way. I just check if a state is see through and if so draw the state directly below it.
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.

This topic is closed to new replies.

Advertisement