Game State Manager

This is a discussion on Game State Manager within the Game Programming forums, part of the General Programming Boards category; Could someone give me the basic - what goes where - when you use a State Manager. A GameState would ...

  1. #1
    Registered User
    Join Date
    Oct 2010
    Posts
    45

    Game State Manager

    Could someone give me the basic - what goes where - when you use a State Manager.

    A GameState would be a virtual class with all the needed to be overloaded methods (i.e. Init(), Update(), Render(), etc).

    A StateManager would swap through the different States as they are called.

    What is causing me some confusion would be the information that all the seperate states would need to work off of, such as the Screen/Window or say images/sounds you want to reuse but not reload every time.

    Lol, programming likes to slap me upside the head ("Hey stupid, look where your design has got you! You should have done it THIS way"). I'm on my 3rd unfinished game now and would like to actually fix this one to finish.

  2. #2
    Registered User
    Join Date
    Nov 2011
    Posts
    48
    Quote Originally Posted by Incantrix View Post
    Could someone give me the basic - what goes where - when you use a State Manager.

    A GameState would be a virtual class with all the needed to be overloaded methods (i.e. Init(), Update(), Render(), etc).

    A StateManager would swap through the different States as they are called.

    What is causing me some confusion would be the information that all the seperate states would need to work off of, such as the Screen/Window or say images/sounds you want to reuse but not reload every time.

    Lol, programming likes to slap me upside the head ("Hey stupid, look where your design has got you! You should have done it THIS way"). I'm on my 3rd unfinished game now and would like to actually fix this one to finish.

    This game tutorial ( http://www.gamefromscratch.com/page/...P-Edition.aspx ) implements a simple GameState system for driving various activities, such as playing the game, showing the main menu, exiting, etc.

    Parts 2 and 3 are the most appropriate areas. If after reading it you still have questions, post away!
    Last edited by Serapth; 12-08-2011 at 09:03 AM.

  3. #3
    Just a pushpin. bernt's Avatar
    Join Date
    May 2009
    Posts
    426
    What is causing me some confusion would be the information that all the seperate states would need to work off of, such as the Screen/Window or say images/sounds you want to reuse but not reload every time.
    For the screen/window I use something like the singleton design pattern.

    Images/sounds, I tend to shift responsibility to some sort of resource manager (the singleton pattern works well here too). It keeps track of which files have been loaded, and their corresponding data, for example a map of filenames to texture handles, so that whenever I need to get a resource, I always do, ie, loadImage(filename). Then the manager checks to see if that entry (filename) is already in the map: if it is, it returns a pointer to that entry; if not, it loads the resource and sticks it in the map (then returns a pointer).
    Consider this post signed

  4. #4
    Registered User
    Join Date
    Oct 2010
    Posts
    45
    I have read in numerous spots that using singletons is very rarely advised. I don't know enough yet personally to make a judgement on it, however judging by the number of responses I have seen on the subject of using them (in this area anyhow, as thats what I have been trying to read up on) the overwhelming concensus is DO NOT USE THEM.

    Although I will read up on your link, and thank you for the response as well.

  5. #5
    Registered User
    Join Date
    Nov 2011
    Posts
    48
    Singletons are currently out of vogue, but that doesn't mean their use is really all that terrible, you just need to be aware of the drawbacks.


    The Singleton was initially proposed as a magic bullet solution to global variables, which in the end, essentially were just global variables in a pretty dress. What happened is people abused the hell out of them, and the problems that go with them are amplified.

    What are the problems? First and foremost, they infect your code. You end up with couplings that simply dont make sense, so if you make a change to your global singleton class, the number of points of possible failure are brutal, as you've used the damned things everywhere. Then you end up with stuff like textures being aware of the (singleton) renderer class, which is a bit of a no no. Additionally, you run into problems when you get into multithreading, but you can cross that bridge when you reach it.


    There are alternatives, like the service locator pattern described in that link above. There are also times where Singletons make sense. Then again, there are also times when global variables make sense too, and you will have some design purists rolling in their grave at the though!

    Generally though, if you think you are replacing a global with a singleton, you really aren't. The number one (good) use for a singleton is deferred allocation of a global resource. To put that into more concrete terms, lets say you have global variables A and B, both of which were quite large and only one of which you are actually going to use... this is where a singleton shines, as using the singleton pattern, memory is only allocated on first use.

  6. #6
    Just a pushpin. bernt's Avatar
    Join Date
    May 2009
    Posts
    426
    I will admit that singletons are perhaps not the best way to go about global states, it's just an obfuscation over the global-ness. I probably should not have specifically mentioned them, there seems to be a lot of disdain directed at the singleton. But I'm still going to argue that when one *has* an inherent global state ("This is the window I'm drawing to", "These are the images that have already been loaded", etc) globals aren't a bad thing at all. It's certainly cleaner, at least to me, than adding a bunch of parameters to all the functions that need access to that information, or having each object keep track of which managers it wants to use.

    I will also mention that both id tech 4 and ogre3d, both considered examples of good design, (while not a full engine ogre3d does have the architecture of an engine) do pretty much I said in the first post wrt resource handling (Ogre3d even uses singletons, but that's another matter entirely, as discussed). Chances are there are more, I've only taken a close look at these two recently. So it can't be all that bad.
    Last edited by bernt; 12-09-2011 at 01:58 PM.
    Consider this post signed

  7. #7
    Registered User
    Join Date
    Oct 2010
    Posts
    45
    Alright, well after much tinkering and more exporing the web I still have a question. I wrote a test program to run, which works.

    Code:
    #include <iostream>
    #include "CState.h"
    #include "CGameState.h"
    #include "CMenuState.h"
    #include "CIntroState.h"
    
    enum STATES { STATE_NULL, STATE_INTRO, STATE_MENU, STATE_GAME, STATE_QUIT };
    
    
    int main()
    {
        bool isRunning = true;
        int highScore = 0;
        int tempState = 0;
    
        CState * currentState = new CMenuState();
        int stateID = STATE_MENU;
    
    
        while( isRunning )
        {
            switch( stateID )
            {
                case STATE_INTRO:
                    currentState->Execute();
                    tempState = STATE_MENU;
                    break;
    
                case STATE_MENU:
                    tempState = currentState->Execute();
                    break;
    
                case STATE_GAME:
                    highScore = currentState->Execute();
                    tempState = STATE_MENU;
                    break;
    
                case STATE_QUIT:
                    isRunning = false;
                    break;
    
                default:
                    break;
            }
    
            // change states  ---  move to own class
            if( tempState && tempState != stateID )
            {
                delete currentState;
    
                switch( tempState )
                {
                    case 1:
                        new CIntroState();
                        break;
    
                    case 2:
                        currentState = new CMenuState();
                        break;
    
                    case 3:
                        currentState = new CGameState();
                        break;
    
                    default:
                        currentState = NULL;
                        break;
                }
    
                stateID = tempState;
                tempState = 0;
            }
    
            if ( highScore )
            {
                std::cout << "\n\nNEW HIGHSCORE!!   *** " << highScore << " ***" << std::endl;
                highScore = 0;
            }
        }
    
    
        return 0;
    }
    
    
    #ifndef CSTATE_H
    #define CSTATE_H
    
    
    class CState
    {
        public:
            CState() {};
            virtual ~CState() {};
            virtual int Execute()=0;
    
        private:
            virtual bool Initialize()=0;
            virtual void Update()=0;
            virtual void Render()=0;
    
    
    };
    
    #endif

    This works all keen and fine, when I derive different classes, such as CGameState. However, the issue I have is in doing it this way is that the derived classes cannot deviate from the blueprint of the base CState. The book I own mentions RTTI by casting, but it also says basically if you use it, it is poor design and agreed upon by everyone online.

    My questions after all of this then are:

    1. How (if any way) can I add data or methods to the derived classes I would be using in such a state machine, still keeping this basic design?

    2. I have also seen an idea to use function pointers in a state manager, could this possibly be a better way?

  8. #8
    Registered User
    Join Date
    Nov 2011
    Posts
    48
    First off, why did you make stateID an int instead of a STATE?

    As a general rule of thumb, function pointers are a C thing. If you are using them, your class design is flawed. Again, just a generalist rule, exceptions exist.

    Second, your understanding of RTTI is mostly wrong. Using RTTI is fine, if the platform you are targeting supports it. There is a small performance penalty, but it is quite minimal. Basically RTTI means exacly what it says, there is a small shim to C++ that preserves runtime type information, allowing your classes to identify what they are ( and what they are derived from ), so when you use for example dynamic_cast<>, it is able to determine if you are actually casting a type to something it actually is. There is of course a small speed penalty to a dynamic_cast over a standard cast, however, compared to casting an object to something it isn't, this can be a small price to pay. Unless you are specifically targeting an environment without RTTI support, (such as some embedded systems, or previously Android NDK, but I believe this is fixed ), or are in a very tight loop, there is little reason to fear RTTI.

    Finally, when it comes to class design system, will steer you right 90% of the time. When modelling something as an object, think "Is A", "Has a" or "Implements a" and that will steer you how best to model it. If it is "Is a", that means you should inhierit it. As the often overused example goes, a Tiger Is A animal, and thus could make sense to derive. That said, a tiger "Has a" set of fangs, so it makes little sense to inherit from a Fanged class, these items are instead "owned" as member variables. Finally "implements a" is perhaps the most confusing. A tiger for example, "Is a runner", but that doesn't really define what it is, more so, it defines what it can do. In these cases, an interface is generally your best bet.

    Following those 3 simple classfications make object design pretty easy to get started.

    In your direct example, it doesn't really make sense to inherit from a state machine, because your derived object "isnt a" state machine, it either "Has a " state machine, meaning it should be implemented as a member variable, or it "implements a " state machine, meaning it should implement an interface.

    Frankly, I would probably go with the later, and implement from an interface such as IStateDriven.

    Make sense?

  9. #9
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    Why are you allocating new states on the heap at runtime? A registration system would work much better and would pre-cache all the state handlers.

    Simply put in its simplest form you want to do this:

    Code:
    if (conditional)
    {
        Foo();
    }
    So you need a state or a conditional and a method or method within an object to handle said state.

    At setup time:
    Code:
    IStateHandler *pHandler = new SpecificStateHandler();
    StateManager->RegisterForState(STATE_INTRO,pHandler);
    ..
    ...
    StateHandler->SetState(STATE_INTRO);
    while (running)
    {
       StateHandler->Update();
    }
    StateHandler will call the appropriate handler for the state.

    Code:
    class IStateHandler
    {
       public:
           virtual ~IStateHandler() { }
           virtual bool HandleState() = 0;
    };
    
    class SpecificStateHandler : public IStateHandler
    {
        public:
           SpecificStateHandler() { }
           virtual ~SpecificStateHandler() { }
    
           virtual bool HandleState()
           {
               // Handle state here   
           }    
    };
    Possible interface for IStateManager
    Code:
    class IStateManager
    {
       public:
          virtual ~IStateManager() { }
          virtual void Update() = 0;
          virtual bool AddState(unsigned int stateID) = 0;
          virtual bool RemoveState(unsigned int stateID) = 0;
          virtual bool RegisterHandler(unsigned int stateID,IStateHandler *pHandler) = 0;
          virtual bool UnregisterHandler(unsigned int stateID,IStateHandler *pHandler) = 0;
          virtual bool SetState(unsigned int stateID) = 0;
    };
    The state manager does not require an enumeration and allows unique states to be added and removed. This state system could potentially allow for multiple handlers for states or it could only allow one handler per state. This is not a complete state machine in its current form as it has no transition handlers or events that transition from state to state. The boolean returns are there as an option for the method to notify of errors. For the sake of brevity I did not check for errors in my sample code.
    Last edited by VirtualAce; 12-21-2011 at 02:35 PM.

  10. #10
    Registered User
    Join Date
    Oct 2010
    Posts
    45
    Well, I didn't impliment a State Handler at all. I used an int, not a STATE, just for simplicity (allowing me to return either a highscore or a menu selection).

    I would not actually do this. I may have alot of poor design, but not quite this bad. Although on this front, I would like to say that learning design seems to come from either learning where you made flaws in the middle of a project or from someone slapping you on the forehead and telling you "no stupid, this way". The programming books I have and the things I find in online searches, inc. tutorials, do nothing to teach you any design.


    The storing of all states would probably be faster and thats a good idea, once I actually can grasp how to get something working.


    Perhaps I am just being obtuse here. So lets say all the different states have the same common methods: Init(), HandleEvent(), Update(), Render(), Cleanup(). But the GameState would need CollisionChecking(). How can you add additional functionality to your States? All the examples I can find use a generic blueprint.

  11. #11
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    Design is something you learn but it does not have to be all through trial and error. There are some very good books on design patterns that will help you with various design approaches. Note that no design is perfect and all have their advantages and disadvantages. It is up to the software engineer to determine which patterns to use and when. Books can help you with a lot of those decisions but a book is not going to tell you how to design or architect your next system, app, or game. If you notice I used a form of the observer / listener pattern in my example which is a very clean object oriented pattern for callbacks and notifications.

    Design is often overlooked and people just want to get down and 'code' but in the end this usually ends in frustration as the project becomes more complex and they quickly realize the end result is tightly coupled code
    that is extremely hard to modify, maintain, and add features to. It is good that you are taking a step back here and analyzing your design for this system because this system is going to make or break your game. The first thing you need to do is figure out what it is that this system must support and what would be 'nice' for it to support. This will help you tailor your design to your specific needs.

    As an example you will see that the system I showed in my example allows for more than one handler per state. This may not be necessary in your system given the requirements of your system. If it is not a requirement then I would remove that functionality and simplify the system a bit more.

    Perhaps I am just being obtuse here. So lets say all the different states have the same common methods: Init(), HandleEvent(), Update(), Render(), Cleanup(). But the GameState would need CollisionChecking(). How can you add additional functionality to your States? All the examples I can find use a generic blueprint.
    You seem to be confused about a few things. The system I showed does not do any rendering. All it does is route states to state handlers so they can then handle the current state appropriately. While Init() can be a state it does not have to be. Update(), Render(), Cleanup(), and CollisionChecking() are also not states. Here is how I see those methods:

    • Init() - called on all relevant objects in the system during startup of a level, world, etc., so they can initialize themselves
    • Update() - called per frame which in turn may call Update() within the various systems and objects so they can update themselves. Since StateManager::Update() will call out to the state handler this is where all state handling occurs
    • Render() - called per frame on all systems and objects which need to render or optionally is a method that renders all current vertex buffers and textures (in a universal rendering system).
    • Cleanup() - called on all systems and/or objects at shutdown (level end, world shutdown, etc.) so each one can cleanup their memory footprint - optionally in a threaded system this could be called at times to cleanup resources that have been marked as no longer being used, etc. (IE: textures, meshes, etc)
    • CollisionChecking() - called per frame for collision detection; upon detection may pass the information to a physics system to handle collision response - CollisionSystem::Update() handles all collision tests for the frame


    Make sure you abstract your behaviors out into objects rather than have one object perform all behaviors. The former promotes loosely coupled code and the latter promotes tightly coupled code. You should be able to change one feature in a key system of your game and this new feature should automatically be available to all objects using said system. Imagine if you put collision checking in a state handler. First off this is not the place for it b/c collisions are not states and second you would have to repeat this code in all objects. It would be better to put this collision detection logic (since it will not differ from object to object) in a centralized system that can grab or maintain collision information about each object it 'knows' about.

    So from this small post you may have the following systems:
    • Render system (renders the current render list)
    • Object system (maintains and grants access to / from all objects)
    • Collision system (tracks and detects all collisions between objects - note that you only have to test collisions between moving objects and between moving objects and static objects. No point in testing between two non-static objects since they will never collide. Most non-static objects in game worlds have very little, if any, physics information attached to them.
    • Physics system (handles all collision responses when detected by the collision system as well as object physics)
    • Game state system (acts as a router that routes control of the game to various state handlers)


    Amazon has several books I recommend you read:
    • Game Engine Architecture
    • Code Complete, 2nd. ed.
    • Game Code Complete, 3rd. ed.
    • Design patterns, Elements of Reusable Object-Oriented Software


    Just type these titles into the Amazon search and they should come up. Some of them are cheap and some not so much but you get what you pay for.
    Last edited by VirtualAce; 12-22-2011 at 01:16 PM.

  12. #12
    Registered User
    Join Date
    Nov 2011
    Posts
    48
    Quote Originally Posted by VirtualAce View Post
    Design is often overlooked and people just want to get down and 'code' but in the end this usually ends in frustration


    It's funny as my career has gone on and I've moved through different positions, how much this has changed. When I first got out of University ( or the horrid code I wrote before ), I was exactly like this... design be damned, it was code code code, hit a road block, code around it. Then again, design patterns weren't so prevalent back then.

    These days though, I actually find the design portion the most exhilarating, and the implementation... well frankly that's mostly just details now. That is, until it comes to debugging and optimization, tasks I love and hate in equal measure.

    The only fear with design patterns is, you soon end up going down the Java road and over engineer the hell out of everything, that is always a trap you need to be wary of.

  13. #13
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    Indeed it is a fine balance but one that is important to any project. For the most part games require a significant amount of design and they are very finicky beasts even with good design. For applications and such design is important as well but b/c often the performance requirement simply isn't as rigid you can get away with a lot more than you can in a game. That being said not all games are performance critical so it really depends on what type of game you are going to program and what engine you are going to buy or perhaps build.

    I do see a tendency with certain software engineering methodologies that favors a code first and design later, if ever, type of mindset and I'm not sure that is a good trend.

    I do apologize if my post insulted your level of knowledge. It is hard to know the expertise level of whom I am talking to on the forum but from your last post you sound as if you have been coding for some time. I was merely trying to provide as much information as I could in one post.
    Last edited by VirtualAce; 12-23-2011 at 02:04 AM.

  14. #14
    Registered User
    Join Date
    Nov 2011
    Posts
    48
    No worries, not insulted, it is hard to gauge knowledge levels; especially in forums.

    Besides, although I've been coding for quite some time, there is nothing to say I'm good at it.

  15. #15
    Registered User
    Join Date
    Oct 2010
    Posts
    45
    If your talking about my level of knowledge, I'm probably BARELY intermediate. I have little to no design expertise, which is probably why this issue is giving me fits (if your talking to Serapth, ignore me completely - haha)


    I was going by a couple simple tuts online originally, which basically seperate everything into its own module. But this falls apart when the seperate modules need additional data/methods.
    State Management - C++ Tutorials | Dream.In.Code
    Lazy Foo' Productions


    The link from Serapth doesn't seem to be a state manager at all, just physically calls the different objects, which is akin to what I was doing. For example, my Highscore list. If you send information in when you call it, it checks the new info for a new score to be added, which then calls Initials to enter your intials. It started occuring to me that there had to be a better way of switching between these, then I got to the idea of a menu within the game and it started running me in circles.

    I'm going to definately check out the listed books (I'm gaining quite a pile as of late, yay for Amazon and used books). I'm also beginning to wonder if I need something written in crayon or fingerpaints...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. State Manager
    By Dark_Phoenix in forum Game Programming
    Replies: 1
    Last Post: 03-25-2007, 10:18 AM
  2. State manager generic data
    By cboard_member in forum Game Programming
    Replies: 3
    Last Post: 06-06-2006, 11:52 AM
  3. current state of game programming
    By Laserve in forum Game Programming
    Replies: 1
    Last Post: 04-28-2005, 06:12 AM
  4. A game memory manager (Just to be different :P)
    By SMurf in forum C Programming
    Replies: 0
    Last Post: 12-02-2002, 07:46 AM
  5. Using time.h in an F1 manager game.
    By marCplusplus in forum C++ Programming
    Replies: 9
    Last Post: 02-08-2002, 05:39 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21