Sign in to follow this  

Game states

This topic is 3495 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The idea is that being at the main menu is very different from playing the game. For one thing, nobody's shooting at you, and there's buttons, and a mouse cursor. I guess that's three things. So you have a variable that tells you which of these situations you're in, and then when it comes time to handle input or draw graphics, you do different things depending on the current state.

Game states are primarily notorious for being heavily overengineered. All you really need is an enum of possible states, and short switch statements for checking which one you're in. You can implement a stack of states if you want to be able to navigate through menus and return from whence you came, but even that's pretty trivial. However, a lot of people -- a little bit drunk on OO -- come up with outlandish yet constraining StateMachine systems which are more difficult to read and to use. Don't be that guy. Don't attack a simple problem with a complicated solution.

Share this post


Link to post
Share on other sites
Quote:
Don't be that guy.


Brilliant! That could be the response to about 40% of the posts in these forums...

But I agree. This is quite possibly one of the simplest game specific programming issues, and also one that gets WAY too much energy focused upon it.

Share this post


Link to post
Share on other sites
Quote:
Original post by Shadowwoelf
Is this a good way to design one?

WinMain
-check to see if any states need updating-

individual states(true)
--logic
--Render()

I'm not sure what you mean by "any states need updating". A state doesn't need updating, because a state isn't an object, just a possible value for a variable. Try this:

Render()
{
switch(gameState)
{
case STATE_MENU: RenderMenu(); break;
case STATE_INGAME: RenderGame(); break;
}
}


.. and similar for what you're calling "logic".

Share this post


Link to post
Share on other sites
Quote:
Don't attack a simple problem with a complicated solution.
There are considerable benefits to using an object-oriented state system, not the least of which is a simple, clean facility for a state stack in a conceptually clean manner. I think you're trivializing the benefits of this approach.

Share this post


Link to post
Share on other sites
typedef std::stack<GameState> SimpleCleanFacilityForAStateStackInAConceptuallyCleanManner;


How's that? Use std::vector instead if you don't like container adapters (I sure don't).

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
The idea is that being at the main menu is very different from playing the game. For one thing, nobody's shooting at you, and there's buttons, and a mouse cursor. I guess that's three things. So you have a variable that tells you which of these situations you're in, and then when it comes time to handle input or draw graphics, you do different things depending on the current state.

Game states are primarily notorious for being heavily overengineered. All you really need is an enum of possible states, and short switch statements for checking which one you're in. You can implement a stack of states if you want to be able to navigate through menus and return from whence you came, but even that's pretty trivial. However, a lot of people -- a little bit drunk on OO -- come up with outlandish yet constraining StateMachine systems which are more difficult to read and to use. Don't be that guy. Don't attack a simple problem with a complicated solution.


Just to clarify, your statement is on the focus of Game states, not all states, right?

I say this because StateMachines are much more powerful than an enum/switch in appropriate situations.

Share this post


Link to post
Share on other sites
Quote:
Original post by Shakedown
Just to clarify, your statement is on the focus of Game states[/b], not all states, right?

Yes, definitely. State machines with many similar, easily and regretlessly parameterizable states are ideal for an OO approach. the "game state" machine does not fit that mold.

Share this post


Link to post
Share on other sites
Edit: whoops I think I misread it. So you have 2 switches. One for logic and the other for rendering? sorta like this?
Logic()

{

switch(gameState)

{

case STATE_MENU: Menu(); break;

case STATE_INGAME: Game(); break;

}

}
Render()
{

switch(gameState)

{

case STATE_MENU: RenderMenu(); break;

case STATE_INGAME: RenderGame(); break;

}

}


Which would end up being a lot of functions...

[Edited by - Shadowwoelf on May 16, 2008 2:50:26 PM]

Share this post


Link to post
Share on other sites
If you where to have an update and a render function then you would need two switch statements. Another way would to just have a simple game loop function which is called each frame, in there you would have one switch statement:


void GameLoop()
{
switch(currentGameState)
{
case GAMESTATE_MAINMENU:
{
UpdateMainMenu();
RenderMainMenu();
}break;

case GAMESTATE_GAME:
{
UpdateGame();
RenderGame();
}break;

case GAMESTATE_CREDITS:
{
UpdateCredits();
RenderCredits();
}break;

default:break;
}
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Shadowwoelf
Which would end up being a lot of functions...

Nah. You'll have number_of_function_slots * number_of_states functions. You can't really get around this number, because this is exactly the number of pieces of functionality you've asked your state machine to access. You'll end up implementing this many functions regardless of whether you choose an all-singing-all-dancing OO extravaganza or a collection of switch statements. (Of course, you can double up these functions between states if two states do the same sort of rendering, for instance.)

Share this post


Link to post
Share on other sites
It's about par for the course for OO-based state machines. At a glance, it involves about twice as much code as doing it the simple way, for (in the case of a game state FSM) no added functionality. It's also a great example of how shoehorning everything into a single state machine decreases readability.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
typedef std::stack<GameState> SimpleCleanFacilityForAStateStackInAConceptuallyCleanManner;


How's that? Use std::vector instead if you don't like container adapters (I sure don't).
LazyFoo's method is, as Sneftel says, about par for the course, but that is more indicative of the problems of "par for the course" than object-oriented development. I've used similar systems as his before and found them inflexible. You might as well be using a delegate or function pointer to a procedure to do the same thing! However, I've begun using the call stack as the state stack, with surprisingly pleasant results. (This is a natural outgrowth of using fully object-oriented languages such as Java and C#; I don't think I would have thought to gone this route in a multiparadigmatic language such as C++.)

In most decent modern languages you can repurpose the call stack to serve better as such, gaining a number of useful benefits such as the aforementioned modal boxes. An external stack reduces these benefits and you have to rely on hackish sub-states within each game state for message passing between states. Conceptually, you can track program flow more easily--states simply pause. when they go out of state. It's perhaps less of a traditional finite state machine, but accomplishes the same task efficiently and cleanly.

Quote:
State machines with many similar, easily and regretlessly parameterizable states are ideal for an OO approach. the "game state" machine does not fit that mold.
I disagree; I think it does fit that mold just fine.

I use something similar to the following in the current game I'm working on (code examples offhand, but C#-ish):

public class StateController
{
protected Boolean isRunning = true;

public StateController() { }

public abstract void Update();
public abstract void Draw();

public virtual void Go()
{
while (this.isRunning)
{
this.Update();
this.Draw();
}
}
}








This lets me do something like this bit below, within SomeStateController and using a DialogBoxController inherited from StateController:

public override void Update()
{
// do some stuff
DialogBoxController dBox = new DialogBoxController("Do you want to answer Yes or No?", DialogBoxController.Buttons.YesNo);
dBox.Go();
Debug.Print(dBox.Result); // will echo something like "Namespace.DialogBoxController.ButtonResult.Yes")
// do more stuff
}





It provides a clean, consistent interface from state to state, and eliminates sub-state "catch it on the next update" hackery. I mean no disrespect, Sneftel, but I think you haven't thought this through. There are benefits to this approach, and I think you're trivializing it due to some dislike of the process. Is there something wrong with this approach that a procedural approach does better?

Share this post


Link to post
Share on other sites
Quote:
Original post by EdR
In most decent modern languages you can repurpose the call stack to serve better as such, gaining a number of useful benefits such as the aforementioned modal boxes. An external stack reduces these benefits and you have to rely on hackish sub-states within each game state for message passing.

The phrase "most decent modern languages" reminds me a bit of the "No true Scotsman" fallacy, particularly given C++'s prevalence in the area. In any case, using the callstack for this involves a great deal of boilerplate code if you want to separate rendering and game code, particularly if the decent modern language in question doesn't give you absolutely perfect reflection facilities. Additionally, it's only really a clever idea when you expect to be stacking your states more than one or two deep, which is extremely rare in games. Finally, the question of whether states are in callstacks or external variables doesn't really bear on the OO/non-OO question.

Quote:
Quote:
State machines with many similar, easily and regretlessly parameterizable states are ideal for an OO approach. the "game state" machine does not fit that mold.
I disagree; I think it does fit that mold just fine.
Not sure how to respond to this, since you haven't given any support for the various attributes.

Quote:
I mean no disrespect, Sneftel, but I think you haven't thought this through. There are benefits to this approach, and I think you're trivializing it.

Having dealt with many, many game code organizations, and many OO and non-OO game state representations, I can tell you categorically that I've thought this through much more thoroughly than I would care to have. [smile]

Share this post


Link to post
Share on other sites
Quote:
The phrase "most decent modern languages" reminds me a bit of the "No true Scotsman" fallacy, particularly given C++'s prevalence in the area.
I was including C++ in this, as I don't see why C++ would have any trouble with it.

Quote:
In any case, using the callstack for this involves a great deal of boilerplate code if you want to separate rendering and game code, particularly if the decent modern language in question doesn't give you absolutely perfect reflection facilities.
Boilerplate code only has to be written once, though, with inheritance (well, if you're reasonably clever with your object structure). :) To address your other point, I can see how reflection facilities would help, but I don't use them for my own--I do most of the rendering work in the StateController base class's Draw function and only do data manipulation (sprite positioning, etc.) in the derived class's.

Quote:
Additionally, it's only really a clever idea when you expect to be stacking your states more than one or two deep, which is extremely rare in games.
Depends on the genre, I'd think. I'm working on a turn-based strategy game that requires repeated code such as UI handlers, so this works pretty well for me. For KillFest ShootEmUp 3000, it'd be almost certainly less valuable.

Quote:
Finally, the question of whether states are in callstacks or external variables doesn't really bear on the OO/non-OO question.
No, but the relatively tight packaging of methods and data can, at least in this case, only help. Encapsulation Is Good(tm). :)

Quote:
Not sure how to respond to this, since you haven't given any support for the various attributes.
Similar: the external interface is going to be the same for more or less any state, at an abstract level, yes? Update/Logic/whatever, and Draw/Render/whatever. Although, with a setup like this, your Go/BeginState function can call whatever's necessary, and other states don't need to know about it anyway.

Easily and regretlessly parameterizable: I don't see how this would not apply, could you give an example?

Quote:
Having dealt with many, many game code organizations, and many OO and non-OO game state representations, I can tell you categorically that I've thought this through much more thoroughly than I would care to have.
Sorry, I was editing my post when you replied, so I'll ask the question again: Is there something wrong with this approach that a procedural approach does better?

Share this post


Link to post
Share on other sites
I tend not to make a habit of this, but I'm going to have to (at least, partially) disagree with Sneftel on this one.

I think state objects are a good thing, for a number of reasons:
  1. They keep the logic/resources/etc bundled up and easy to modify without the worry of affecting other states.
  2. Beyond a few states, perhaps 3-5, they make code more readable in my opinion.
  3. They allow you to destroy states which are used infrequently.
  4. State objects allow you to easily support transitional actions (things to do when a state is made active/inactive) such as OnPush()/OnPop() which suspend/restore the state respectively.
  5. Destruction and suspension of states allow associated resources to be freed or marked for garbage collection easily.

If the game is very simple, then a simple switch statement may do -- thats the way we used to do it, after all.

When the game becomes more complex, however, large switch statements, or nested switch statements (often across a function call) can become difficult to follow and they are always more prone to changes in one state affecting another. Further, if your life would be made simpler being able to have transitional actions, then state objects are the way to go -- you wouldn't want to add several "transition states" for each game state, would you?

For me, I've found the stack-based approach to be most useful overall, but the requirements for my games have typically been the go-in/back-out variety which maps precisely to a push/pop setup. For more free-form transitions, a state-machine approach might make sense. I've also found that the hybrid approach, where some states on the stack have small, internal state machines driving them, to be useful -- the battle state in a jRPG for instance.

One issue I've encountered is that, in my stack-based system, I've run across situations in which a state needs to pop itself. In my last system, a state object is immediately destroyed when it is popped, so the state object was essentially calling delete(this) -- which *can* be done, but only safely under very specific constraints, some of which are difficult to guarantee. In the end, this is best avoided, and can be by deferring destruction until after the state is no longer being executed. This can be implemented in a number of ways -- a modified stack, message-passing, return codes...

Share this post


Link to post
Share on other sites
Quote:
Original post by EdR
Quote:
The phrase "most decent modern languages" reminds me a bit of the "No true Scotsman" fallacy, particularly given C++'s prevalence in the area.
I was including C++ in this, as I don't see why C++ would have any trouble with it.

Quote:
In any case, using the callstack for this involves a great deal of boilerplate code if you want to separate rendering and game code, particularly if the decent modern language in question doesn't give you absolutely perfect reflection facilities.
Boilerplate code only has to be written once, though, with inheritance (well, if you're reasonably clever with your objectstructure). :) To address your other point, I can see how reflection facilities would help, but I don't use them for my own--I do most of the rendering work in the StateController base class's Draw function and only do data manipulation (sprite positioning, etc.) in the derived class's.

I think we might be talking at cross-purposes. When you mentioned "using the callstack as a state stack", I took that to mean using normal code flow facilities to implement long-running game states. In event-driven or constant-update scenarios, that requires that either the state stack be running in its own execution thread, or that the event loop operate above the state stack in the call stack. The first one I've seen done, but it's only really pleasant to do if you have cooperative multithreading. The second one I've rarely actually seen, so I doubt if you're talking about that one, but let me know if you are.

Quote:
Quote:
Additionally, it's only really a clever idea when you expect to be stacking your states more than one or two deep, which is extremely rare in games.
Depends on the genre, I'd think. I'm working on a turn-based strategy game that requires repeated code such as UI handlers, so this works pretty well for me. For KillFest ShootEmUp 3000, it'd be almost certainly less valuable.
What's an example of deeply stacked states in the TBS game?

Quote:
Similar: the external interface is going to be the same for more or less any state, at an abstract level, yes? Update/Logic/whatever, and Draw/Render/whatever. Although, with a setup like this, your Go/BeginState function can call whatever's necessary, and other states don't need to know about it anyway.
Ah, but you missed the most important one: "many". The mere machinery of an OO state stack, with all the trimmings, easily runs to at least a couple hundred lines of code beyond what you'd be doing without such a thing. The organizational benefits outweight the costs eventually, but only when you've got dozens and dozens of states. Properly normalized game state machines don't tend to have more than half a dozen.

Quote:
Easily and regretlessly parameterizable: I don't see how this would not apply, could you give an example?
It applies here only in a trivial fashion, in that there's nothing to parameterize. Consider a state machine with states A, B, C1, C2, C3, ... C253, and D. Here it makes complete sense to represent this as four state classes, one of which is parameterized on an individual integer.

Quote:
Sorry, I was editing my post when you replied, so I'll ask the question again: Is there something wrong with this approach that a procedural approach does better?
No. The decomposition from a procedural approach to an OO approach is simple and mechanical, so there can't be. The benefits of a procedural approach are simplicity, and (more fundamentally) the opportunity to gain a better understanding of the relationship between a piece of code's complexity, its importance, and its pervasion.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by EdR
Quote:
The phrase "most decent modern languages" reminds me a bit of the "No true Scotsman" fallacy, particularly given C++'s prevalence in the area.
I was including C++ in this, as I don't see why C++ would have any trouble with it.

Quote:
In any case, using the callstack for this involves a great deal of boilerplate code if you want to separate rendering and game code, particularly if the decent modern language in question doesn't give you absolutely perfect reflection facilities.
Boilerplate code only has to be written once, though, with inheritance (well, if you're reasonably clever with your objectstructure). :) To address your other point, I can see how reflection facilities would help, but I don't use them for my own--I do most of the rendering work in the StateController base class's Draw function and only do data manipulation (sprite positioning, etc.) in the derived class's.

I think we might be talking at cross-purposes. When you mentioned "using the callstack as a state stack", I took that to mean using normal code flow facilities to implement long-running game states. In event-driven or constant-update scenarios, that requires that either the state stack be running in its own execution thread, or that the event loop operate above the state stack in the call stack. The first one I've seen done, but it's only really pleasant to do if you have cooperative multithreading. The second one I've rarely actually seen, so I doubt if you're talking about that one, but let me know if you are.
I am referring to the former. I have an input thread running separately, generating input events into a list; the base functions of the StateController class parses them, invokes UI handler delegates, and passes those not handled by the UI (and thus being handled by the main game itself) into the Update() function of the derived state class. For a menu state, these extra input values are tossed out; a click that isn't on a UI widget is unimportant, for example, as are keyboard events not caught by a widget like a text box.

While threading isn't easy, this sort of black-box threading is really quite trivial to implement; I would be very worried about a programmer who couldn't grasp this sort of simple design. I'm not sure in C++, but I can't see it being that difficult; in C# or Java, it is perhaps five lines to call the thread, then just wrapping input events in the format the rest of your program understands and working from there.

Quote:
Quote:
Quote:
Additionally, it's only really a clever idea when you expect to be stacking your states more than one or two deep, which is extremely rare in games.
Depends on the genre, I'd think. I'm working on a turn-based strategy game that requires repeated code such as UI handlers, so this works pretty well for me. For KillFest ShootEmUp 3000, it'd be almost certainly less valuable.
What's an example of deeply stacked states in the TBS game?
Submenus. I modeled my GUI paradigm on the "Form" class of System.Windows.Forms; each separate "form" is a separate state. Occasionally I go about 4-5 deep, plus modal dialog boxes in some areas (main game map, "headquarters" screen, advisor panel, advanced functions for that advisor with which I don't want to clutter up the information screen, and so on). Instead of having to find a suitable place to pause the main game state, I just call out to the modal menus (which save the current screen surface as a background for any drawing effects over it), and continue operation from wherever they were invoked once the user's done there.

Quote:
Quote:
Similar: the external interface is going to be the same for more or less any state, at an abstract level, yes? Update/Logic/whatever, and Draw/Render/whatever. Although, with a setup like this, your Go/BeginState function can call whatever's necessary, and other states don't need to know about it anyway.
Ah, but you missed the most important one: "many". The mere machinery of an OO state stack, with all the trimmings, easily runs to at least a couple hundred lines of code beyond what you'd be doing without such a thing. The organizational benefits outweight the costs eventually, but only when you've got dozens and dozens of states. Properly normalized game state machines don't tend to have more than half a dozen.
Denormalization is sometimes valuable, though. I don't want to stuff all my menus in a single state under this approach; it's far cleaner and far simpler to just make a new state for each one.

Quote:
Quote:
Easily and regretlessly parameterizable: I don't see how this would not apply, could you give an example?
It applies here only in a trivial fashion, in that there's nothing to parameterize. Consider a state machine with states A, B, C1, C2, C3, ... C253, and D. Here it makes complete sense to represent this as four state classes, one of which is parameterized on an individual integer.
I agree. I do this.


(new ParameterStateController(1)).Go();
(new ParameterStateController(2)).Go();
...
(new ParameterStateController(253)).Go();


Nothing says you can't have a constructor take an argument, does it? :)

Quote:
Quote:
Sorry, I was editing my post when you replied, so I'll ask the question again: Is there something wrong with this approach that a procedural approach does better?
No. The decomposition from a procedural approach to an OO approach is simple and mechanical, so there can't be. The benefits of a procedural approach are simplicity, and (more fundamentally) the opportunity to gain a better understanding of the relationship between a piece of code's complexity, its importance, and its pervasion.
I don't really see the "simplicity" argument here, except in the case of programmers who don't really know object-oriented development very well. (Not referring to you, just in general.) I would also say that the object-oriented approach allows for more natural linking between states from a conceptual standpoint as well.

Share this post


Link to post
Share on other sites
Quote:
Original post by EdR
I am referring to the former. I have an input thread running separately, generating input events into a list; the base functions of the StateController class parses them, invokes UI handler delegates, and passes those not handled by the UI (and thus being handled by the main game itself) into the Update() function of the derived state class. For a menu state, these extra input values are tossed out; a click that isn't on a UI widget is unimportant, for example, as are keyboard events not caught by a widget like a text box.

That doesn't speak to state management, though. Having a thread that handles input is fine, but that thread obviously isn't using its callstack for state management, because it's using it for input. I think there still might be a miscommunication here... are you saying that for your proposed design, there's a particular thread being the state stack, with a callstack whose top looks like this?


SubMenuState()
MenuState()
InGameState()
MainState()


Quote:
Quote:
What's an example of deeply stacked states in the TBS game?
Submenus. I modeled my GUI paradigm on the "Form" class of System.Windows.Forms; each separate "form" is a separate state. Occasionally I go about 4-5 deep, plus modal dialog boxes in some areas (main game map, "headquarters" screen, advisor panel, advanced functions for that advisor with which I don't want to clutter up the information screen, and so on). Instead of having to find a suitable place to pause the main game state, I just call out to the modal menus (which save the current screen surface as a background for any drawing effects over it), and continue operation from wherever they were invoked once the user's done there.

Quote:
Quote:
Similar: the external interface is going to be the same for more or less any state, at an abstract level, yes? Update/Logic/whatever, and Draw/Render/whatever. Although, with a setup like this, your Go/BeginState function can call whatever's necessary, and other states don't need to know about it anyway.
Ah, but you missed the most important one: "many". The mere machinery of an OO state stack, with all the trimmings, easily runs to at least a couple hundred lines of code beyond what you'd be doing without such a thing. The organizational benefits outweight the costs eventually, but only when you've got dozens and dozens of states. Properly normalized game state machines don't tend to have more than half a dozen.
Denormalization is sometimes valuable, though. I don't want to stuff all my menus in a single state under this approach; it's far cleaner and far simpler to just make a new state for each one.

Why is your GUI code in your main game state? Why hasn't it been encapsulated into its own state system? After all, encapsulation Is Good(tm). (Sorry, couldn't resist.) That gives you the ideal simplicity for your main state, and lets you do your GUI state stack in a way that is ideal for GUI state stacks.

Quote:
I don't really see the "simplicity" argument here, except in the case of programmers who don't really know object-oriented development very well. (Not referring to you, just in general.) I would also say that the object-oriented approach allows for more natural linking between states from a conceptual standpoint as well.
Simplicity isn't just for newbs. It is its own reward.

Share this post


Link to post
Share on other sites
Wait, Sneftel and others are now confusing me. What's wrong with this simplistic piece of code:

struct GameState {
GameState() {}
virtual ~GameState() {}
virtual void update() = 0;
};

struct MenuState: GameState {
MenuState() {}
void update() {
gui->update();
gui->render();
}
};

typedef std::vector<GameState*> GameStateStack;

GameStateStack gameStates;
gameStates.push_back(new MenuState());

while (running) {
gameStates.back()->update();
}

void destroyState(GameState *gs) {
delete gs;
}

// memory leaks xD
std::for_each(gameStates.begin(), gameStates.end(), &destroyState);
gameStates.clear();


Now you can introduce loads of new types of game states in an extremely clean, simple matter. And you can make use of the mentioned "onPush" and "onPop" methods to create/cleanup the resources/scene/etc (for example, MenuState::onPop would call gui->destroyWidget(menuWindow)).

Share this post


Link to post
Share on other sites
The last part I'm confused on is how to pass the data.
From
UpdateMainMenu();
To
RenderMainMenu();

So lets assume your starting off the game so the game state would be on the MainMenu (as default). It would first go to UpdateMainMenu(); then after it figures out any input it quites and then goes to RenderMainMenu();. But how does the RenderMainMenu know what to render?

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by EdR
I am referring to the former. I have an input thread running separately, generating input events into a list; the base functions of the StateController class parses them, invokes UI handler delegates, and passes those not handled by the UI (and thus being handled by the main game itself) into the Update() function of the derived state class. For a menu state, these extra input values are tossed out; a click that isn't on a UI widget is unimportant, for example, as are keyboard events not caught by a widget like a text box.

That doesn't speak to state management, though. Having a thread that handles input is fine, but that thread obviously isn't using its callstack for state management, because it's using it for input. I think there still might be a miscommunication here... are you saying that for your proposed design, there's a particular thread being the state stack, with a callstack whose top looks like this?


SubMenuState()
MenuState()
InGameState()
MainState()

If it were procedural, yes, that's somewhat similar to how it looks.

Quote:
Quote:
Quote:
Quote:
Similar: the external interface is going to be the same for more or less any state, at an abstract level, yes? Update/Logic/whatever, and Draw/Render/whatever. Although, with a setup like this, your Go/BeginState function can call whatever's necessary, and other states don't need to know about it anyway.
Ah, but you missed the most important one: "many". The mere machinery of an OO state stack, with all the trimmings, easily runs to at least a couple hundred lines of code beyond what you'd be doing without such a thing. The organizational benefits outweight the costs eventually, but only when you've got dozens and dozens of states. Properly normalized game state machines don't tend to have more than half a dozen.
Denormalization is sometimes valuable, though. I don't want to stuff all my menus in a single state under this approach; it's far cleaner and far simpler to just make a new state for each one.

Why is your GUI code in your main game state? Why hasn't it been encapsulated into its own state system? After all, encapsulation Is Good(tm). (Sorry, couldn't resist.) That gives you the ideal simplicity for your main state, and lets you do your GUI state stack in a way that is ideal for GUI state stacks.
Because I have GUI objects in all states. I have command buttons (reskinned to look different, but they're still command buttons) on the main map for various tasks. There is no reason to remove GUI code from the "normal" state controller because it's always in use. And really, there is almost no overhead to the GUI system I have implemented when no GUI widgets are on screen.

Quote:
Quote:
I don't really see the "simplicity" argument here, except in the case of programmers who don't really know object-oriented development very well. (Not referring to you, just in general.) I would also say that the object-oriented approach allows for more natural linking between states from a conceptual standpoint as well.
Simplicity isn't just for newbs. It is its own reward.
I don't disagree. I was referring to that I don't see how procedural is any simpler, especially in a codebase that is already largely object-oriented.

Share this post


Link to post
Share on other sites

This topic is 3495 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this