Quote:Original post by Kylotan
Quote:Original post by agi_shi
Hm, excellent idea about the rendering. Should any kind of updating be done as well? I'm not sure how I'd tell which states would need updating if it's not only the one on the top of the stack.
I'd say yes. If a state is paused, it can set a pause flag before the next state is pushed on top, and choose not to do anything during its update. Normally you might want updates to continue as usual. eg. in a multiplayer FPS, if you bring up a menu, you might still want to see enemies running past in the background. But really it depends on your game - it might be easier just to only update the top state.
That's another good point. So I can basically iterate through the stack, and any state that doesn't want to update/render if it's not on the top, can figure that out on its own. Besides, the rendering will be best done bottom to top.
Quote:
Quote:Well, this was the main part I wasn't entirely sure how to go about. What I ended up doing at first is to register the states with the stack (operator+=), and then actually push them onto the stack using their names
What part of the system does the look up between a name and the state object?
The states manager, stateStack. Take a look at my example above:
stateStack states;states += statePtr(new playState(...));states += statePtr(new editorState(...));states += statePtr(new creditsState(...));states += statePtr(new mainMenuState(...));
The stateStack is used to register various available states. They are stored in an std::map, where the key is their name (which is where the look-up comes from). Their name is chosen by themselves - meaning, the base state class needs to be provided a name, and the deriving states are the one to provide it:
mainMenuState::mainMenuState(...): state("mainMenu"), // give constructor of state a name ...{ ... }
So now all you need to do is provide a name:
states << "mainMenu";
Quote:
I think it would be better if you just ditched that, and created the state objects locally, pushing them directly on. This lets you parameterise it more easily, eg:if (keypress==KEY_MAIN_MENU) states.push(new MenuState("main_menu.xml"));if (keypress==KEY_OPTIONS_MENU) states.push(new MenuState("options_menu.xml"));
Quote:This way, the states that a run don't have to know about the actual instances of the other states, they only need to know the common name of what they want next.
Given how few states you're likely to have, I don't think that's a benefit worth working for.
Hm, do you really think so? After failing to design a proper engine the first time, this time I'm
really questioning things and thinking them over [smile]: should any given state know about the implementation details of any other states it wishes to push onto the stack? Or should the higher-level ower of the stateStack know about the state implementation details, only (such that it tells the stateStack what is available and what is not)? (this is the way I'm doing it right now)
With your particular example, the owner of the stateStack would push multiple menuStates, and give them different names. Which, then brings up another point: since my states name themselves, this would not be possible. Thus, I'd need to separate the naming from the actual state types (there wouldn't be a 1:1 correspondence). Which also means that the states shouldn't have any names to begin with, only the stateStack should contain names.
Edit:So this is what I came up with (just as an example):
game::stateStack states;states += namedState("keyMenu", statePtr(new menuState("key_menu.xml")));states += namedState("graphicsMenu", statePtr(new menuState("gfx_menu.xml")));states += namedState("physicsMenu", statePtr(new menuState("phys_menu.xml")));states += namedState("mainMenu", statePtr(new menuState("root_menu.xml")));states << "mainMenu";// button callback, buttons are found in the XML configuration file// only buttons that should change the state are assigned this callbackvoid menuState::stateButtonClickCallback(gui::button *b){ stateChange = b->caption();}void menuState::tick(engine::real dt, stateStack &states){ if (!stateChange.empty()) states << stateChange;}
Thanks!
[Edited by - agi_shi on July 22, 2008 9:17:58 AM]