|
|
View previous topic - View next topic |
Author |
Message |
DeveloperX 202192397
Joined: 04 May 2003 Posts: 1626 Location: Decatur, IL, USA
|
Posted: Thu Aug 31, 2006 6:26 pm Post subject: your game state management method |
[quote] |
|
I'm curious, what method do you use for managing your game's game state?
I've seen the use of a simple int for tracking and a switch() to determine the state in the game, and I've seen a class for managing the state used by pushing and popping the states on a stack.
I want to know how you handle your game states.
I'm wondering what is the best way.
I know there really is no _BEST_ way, but theres always a more acceptable method, or a method that most people use.
Anyone with a few minutes to explain their method? _________________ Principal Software Architect
Rambling Indie Games, LLC
See my professional portfolio
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: Thu Aug 31, 2006 10:40 pm Post subject: |
[quote] |
|
Application of the State Design Pattern. (Note: that link is actually rather bad, as perusal of the talk page would suggest. However, a quick google pops up this discussion, which is probably more factual. (EDIT: actually, that latter discussion is slightly obtuse and debatable, mostly because the author asserts that the state pattern is intrinsically linked to the strategy pattern, which is not strictly true (they are designed to address different problems); this looks to be slightly better. (EDIT: Ack! Goddammit: I really need to read this shit before I link to it; the FSM example in that latter document would be a good solution, if it were not for that messy switch statement. A good implementation of the State pattern should eliminate the need for switching.)))
So, essentially, the idea would be to encode each possible state(*) in a class which, upon a given type of input, transitions to the next state in your state-graph. This keeps the code in the controller object extremely simplistic and type-agnostic.
(*) The assumption runs that "possible states" are few enough as to be manageable. For instance, a simple platformer might have, say, three states: (Main-)Menu, Stage, and StageResults. _________________ "...LeoDraco is a pompus git..." -- Mandrake
|
|
Back to top |
|
|
DeveloperX 202192397
Joined: 04 May 2003 Posts: 1626 Location: Decatur, IL, USA
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: Fri Sep 01, 2006 2:29 am Post subject: |
[quote] |
|
Heh: Sorry about that.
Some more in depth googling came up with a discussion that looks slightly more intuitive; there are also more links over here. To make my erratic discussion above slightly more sane, how about the following discussion?
The state pattern gives a way to model states, in the sense of states in a finite-state machine graph: each state encapsulates implementations of abstract transition methods, which is to say, that each state class provides the functionality to transition to other states. In the contrived example I gave in the first post, we could think of each state as being a rendering/input context (that is, each state provides state-specific functionality for recieved input and for rendering output) which is autonomous of the other states. These state-specific responses to input could branch to other states, should that be needed; in the platformer, for example, the user can press a key (say the escape key) to toggle between the MainMenu and Stage classes; this could (although should not necessarily) be implemented by having their interface define a method, "PressedEscape," which both subclasses implement. MainMenu would cause its controller to transition to the Stage object, whereas Stage would cause its controller to transition to the MainMenu object.
While all of this might just appear to be shuffling functionality around --- e.g. rather than defining all state-specific information within a single function, switching as appropriate, the functionality to thrown off to classes elsewhere within the framework --- it has the opportunity to be much more, especially if the number of states within the project is subject to change.
This whole discussion is predicated on the assumption that by "game state" you are, in fact, referring to the state of the game's engine, i.e. what its current rendering-, input-/event-, and logic- contexts are. If, on the other hand, you were referring to something more along the lines of data which, essentially, must be persisted to return the game to a specific state, I could describe a different design pattern which would be applicable. _________________ "...LeoDraco is a pompus git..." -- Mandrake
Last edited by LeoDraco on Fri Sep 01, 2006 3:16 am; edited 1 time in total
|
|
Back to top |
|
|
Nodtveidt Demon Hunter
Joined: 11 Nov 2002 Posts: 786 Location: Camuy, PR
|
Posted: Fri Sep 01, 2006 3:04 am Post subject: |
[quote] |
|
I tend to use procedural-based finite state machines, generally using the switch() and int method. There really is no best method to use...you use what fits the application. _________________ If you play a Microsoft CD backwards you can hear demonic voices. The scary part is that if you play it forwards it installs Windows. - wallace
|
|
Back to top |
|
|
Rainer Deyke Demon Hunter
Joined: 05 Jun 2002 Posts: 672
|
Posted: Fri Sep 01, 2006 3:38 am Post subject: |
[quote] |
|
When I can get away with it, I just use functions. Something like this: Code: | void main_menu() {
// In main menu state...
for (;;) {
// ...
if (something) run_game();
}
}
void run_game()
{
// In normal gameplay state...
for (;;) {
// ...
if (something) run_game_menu();
}
}
void run_game_menu()
{
// In game menu state...
// ...
} |
Of course it's not quite that clean and simple for actual games. However, there is nothing wrong with starting out like this and changing to a more sophisticated system when the need arises.
|
|
Back to top |
|
|
DeveloperX 202192397
Joined: 04 May 2003 Posts: 1626 Location: Decatur, IL, USA
|
Posted: Fri Sep 01, 2006 4:15 am Post subject: |
[quote] |
|
LeoDraco:
I generally use the following method:
Code: |
#define ST_TITLE 0
#define ST_PLAY 1
#define ST_GAMEOVER 255
int gamestate;
..
while(gamestate!=ST_GAMEOVER)
{
switch(gamestate)
{
case ST_TITLE:{gamestate=ST_PLAY;}break;
case ST_PLAY:{if(checkkeys[VKESC]==1)gamestate=ST_TITLE;}break;
}
}
|
and I wanted to know a more suitable method to use for larger projects, such as a commercial-grade game.
To all: I highly appreciate everyone's input on the subject. I am reading everyone's posts, and any links to which they lead. I am enjoying seeing things from each point of view. Thank you. _________________ Principal Software Architect
Rambling Indie Games, LLC
See my professional portfolio
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: Fri Sep 01, 2006 10:04 am Post subject: |
[quote] |
|
Right, that is what I thought you meant. Which was why I went on that tirade (nonsensical though it might have been) about the state pattern. I probably should have dumped that last paragraph in the second post in my first post. Or something.
In case my argument, here, is still lost in translation, consider the following: the solution you and nodtveidt are championing consists of representing states and the transitions between those states through use of fundamental data types and switching mechanisms. While this works, it is not very sophisticated, and can lead to problems if you want any form of maintainability within a large project. Rainer Deyke's solution is more sophisticated: his states are represented by a slightly more abstract concept compared to the low-level approach; even better, he can have state-specific data (i.e. function local variables) which is separate from the data of other states. However, it still --- at least, given the code posted --- has the intrinsic problem of tying control code with state logic. My suggestion would be to encapsulate the idea of a state as a set of types adhering to an interface which represents the idea of your gameplay state.
To make this slightly more concrete, let's look at an example, in which the game's engine responds to events lobbed at it by some external agent. (For the purposes of this discussion, it would probably suffice to say that the "external agent" is some object which sits and polls for user input and, at set points in time, asks for a screen refresh.)
Code: | namespace Game
{
class Engine
{
public interface State
{
void Render();
State KeyPress( Keys Which );
State MouseClick( Point Location );
}
public void HandleRender()
{
this.InternalState.Render();
}
public void HandleKeyPress( Keys Which )
{
this.InternalState = this.InternalState.KeyPress( Which );
}
public void HandleMouseClick( Point Location )
{
this.InternalState = this.InternalState.MouseClick( Location );
}
private State InternalState;
}
}
|
From this template, it should be self-evident that the Engine delegates its state changes to its current state object, which has logic necessary to describe its transitions (State::KeyPress and State::MouseClick) as well as state-specific operations (State::Render). How about a few game states to tie this together?
Code: | class Title : Engine::State
{
void Render()
{
/* Code to display title screen */
}
/*
* Notice how the title screen will shift to the main menu
* regardless of input.
*/
State KeyPress( Keys Which )
{
return new MainMenu();
}
State MouseClick( Point Location )
{
return new MainMenu();
}
}
class MainMenu : Engine::State
{
void Render()
{
/* Code to display the main menu */
}
State KeyPress( Keys Which )
{
return Keys.Escape == Which ? new Stage() : new Exit();
}
State MouseClick( Point Location )
{
/* Etc... */
}
}
|
While this code is far from perfect --- it would be all too easy to degenerate down to testing individual keys from within a given state in a massive switch like-construct, and never mind what happens to heap-allocated objects or reusable states --- the point of this is to get across the organizational benefits: all transitions, functionality, and data related to a specific state is located in one place separate from that of all other states. Adding states is easy, and in pretty much enforced statically by your compiler (depending upon language, naturally), which is not guaranteed (or even strictly possible) with the int/switch solution. _________________ "...LeoDraco is a pompus git..." -- Mandrake
|
|
Back to top |
|
|
DeveloperX 202192397
Joined: 04 May 2003 Posts: 1626 Location: Decatur, IL, USA
|
|
Back to top |
|
|
cowgod Wandering Minstrel
Joined: 22 Nov 2005 Posts: 114 Location: Pittsburgh, USA
|
Posted: Sat Sep 02, 2006 2:45 pm Post subject: |
[quote] |
|
I use Java, and I use their Swing gui toolset in my games.
With Swing, I just put the title screen, the credits screen, the game screen, etc. in seperate panels. Then I add all the panels to a CardLayout and switch which panel is being displayed whenever I switch to a different screen.
CardLayout stores a "state" in that it stores which panel is being displayed, but it's not an example of the "State" design pattern. My approach as a whole uses the "State" design pattern in a trivial kind of way. I render and listen to input differently for each panel, but it's more a consequence of using Swing than any attempt of mine to use a design pattern.
I store things like pausing the game seperately because pausing the game only affects the game screen.
|
|
Back to top |
|
|
Nephilim Mage
Joined: 20 Jun 2002 Posts: 414
|
Posted: Wed Sep 06, 2006 6:17 am Post subject: |
[quote] |
|
For Sacraments, I used something pretty similar to what LeoDraco is talking about - a separate class for each game state that knows how to render itself and respond to user input, which then swaps itself in and out with other instances of the class for each possible game state. In the case of Sacraments, I implemented it as a stack and called render() all the way up the stack, so that you could pop interfaces on top of interfaces, like windows over the map. I also split out the render() and the timepasses() functionality, so that you could decide whether time "froze" for non-top-of-stack game states or not. The whole thing is described in the article I wrote about it here.
Since writing Sacraments, I've done more work with this method of doing things, and I've gravitated more towards what LeoDraco described, with just a single game state class that handles things, which just hands itself off to other game states - no "stack." Things that would normally have been game states pushed onto the stack are now split out between their game state functionality and their visual stuff using a model-view-controller paradigm, which has worked fantastically well for me. That's how the Science Pirates game I'm working on now is architected, and it's a flexible enough setup that I can pretty much do whatever I want with it. _________________ Visit the Sacraments web site to play the game and read articles about its development.
|
|
Back to top |
|
|
|
Page 1 of 1 |
All times are GMT
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|