Hey, I think this is the best way to do game states. There is very good code in this article. Small suggestion I have is to give a little more background into states and why we are using that code. I would also love to see mouse input being handled with this! Well done!
--Rocifier 22:26, 13 December 2005 (CST)

Activating & Deactivating instead of Loading / Unloading

Hiya,

I wanted the ability to just activate and deactivate states. This was useful to be able to return to the game after visiting the menu state with minimum "load" time.

I was able to achieve this by changing GameState to

 class GameState
 {
 private:    
    enum States {Unloaded, Loaded, Active};
 
 public:
    void load()
    {
        if (State == Unloaded)
        {
            loadState();
            State = Loaded;
        }
        else
        {
            std::cerr << "State NOT UNLOADED to move to Loaded";
        }
    }
    void activate(Ogre::RenderWindow* mWindow) 
    { 
        
        switch (State)
        {
            case Unloaded:
                load();
            case Loaded:
                activateState(mWindow);
                State = Active;
            case Active:
                break;
        }
    }
    
    void deactivate()
    {
        if (State == Active)
        {
                deactivateState();
                State = Loaded;
        }
        else
        {
            std::cerr << "State NOT ACTIVE to DeActivate " << State << std::endl;;
        }
    }
    
    void unload()
    {
        switch (State)
        {
            case Active:
                deactivate();
            case Loaded:
                unloadState();
                State = Unloaded;
            case Unloaded:
                break;
        }
    }
    
    virtual void pause() = 0;
    virtual void resume() = 0;
 
    virtual void keyClicked(Ogre::KeyEvent* e) = 0;
    virtual void keyPressed(Ogre::KeyEvent* e) = 0;
    virtual void keyReleased(Ogre::KeyEvent* e) = 0;
    virtual bool frameStarted(const Ogre::FrameEvent& evt) = 0;
    virtual bool frameEnded(const Ogre::FrameEvent& evt) = 0;
 
    void changeState(GameState* state) { Anubhava::getSingletonPtr()->changeState(state); }
    void pushState(GameState* state) { Anubhava::getSingletonPtr()->pushState(state); }
    void popState() { Anubhava::getSingletonPtr()->popState(); }
    
    virtual ~GameState() { }
 protected:
 
    virtual void loadState() = 0;
    virtual void activateState(Ogre::RenderWindow* mWindow) = 0;
    virtual void deactivateState() = 0;
    virtual void unloadState() = 0;
 
    States State;
    GameState() : State(Unloaded) { }
 
 };

I also changed the gamemanager to call deactivate and activate instead of load and unload.

The states of course needed the methods renamed to have the State suffix and be protected.

The clean-up / unloading of states will have to be done either as garbage collection in game manager or, for better control within the states themselves. i.e. unload level1 state on level2 state and so on.

I hope this is useful and I would appreciate any comments.

Just a Thought

Most people will be using this system to create a menu system (as well as an intro system). With the integrated CEGUI system, a great tutorial would include this in the intro and "pause" system. It's a bit hard for even an intermediate programmer to jump straight from the "example" applications to the state-based formats of the game with the limited commenting.

Loading Materials

I've used this tutorial to start a little 3rd person framework with the Ninja as a model. I always got the error that the material Examples/Ninja could not be assigned, although the paths and resources were correctly added. After a while I noticed, by comparing a ogre.log file of the Ogre examples and my .log file, that in the examples the resources are added before any of the GPU stuff is done.

I checked the configure, setupResources and start methods again and noticed that setupResources is only called when configure returns false. That way, the setupResources method is never called. Is this a mistake or was this just not working in my case?

I just added a call to setupResources on the first line of the configure method and it fixed all my troubles.
--Stenne 16:34, 10 April 2007 (BST)