Thread: State Manager

  1. #1
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174

    State Manager

    I'm trying to create a class to manage the various game states for my engine (main menu, gamescreen, ect...) I think I'm on the right track here but I can't get anything to render to the screen.
    Here is my manager class...
    Code:
    enum Purpose {
        SM_INIT = 0,
        SM_RESET,
        SM_PROCESS,
        SM_UPDATE,
        SM_RENDER,
        SM_LOST,
        SM_SHUTDOWN,
        SM_NO_PURPOSE
    };
     
    class CStateManager {
    private:
        typedef void(*pFunction)(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void *DataPtr);
        std::vector<pFunction> States;
        std::vector<pFunction>::iterator StateIter;
    public:
        CStateManager()  { }
        ~CStateManager() { PopAll(); }
        bool Push(void (*Function)(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void *DataPtr) );
        bool Pop();
        void PopAll() { States.clear(); }
        bool Process(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void* pData = NULL);
    };
     
    bool CStateManager::Push(void (*Function)(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void* pData) ) {
        // Don't push a NULL value
        if(Function != NULL) {
            // Push new function onto stack
            States.push_back(Function);
            return true;
        } else return false;
    }
     
    bool CStateManager::Pop() {
        // Remove the head of stack (if any)
        if(!States.empty() ) {
            States.pop_back();
        }
        // return TRUE if more states exist, FALSE otherwise
        if(States.empty() )
            return false;
        return true;
    }
     
    bool CStateManager::Process(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void* pData) {
        // return an error if no more states
        if(States.empty() )
            return false;
        // Process the top-most state
        StateIter = States.end() - 1;
        (*StateIter)(pDevice, pCaller, Purpose, pData);
        return true;
    }
    My game state function prototypes and definitions...
    Code:
    class CGameApp {
    public:
        .....
        static void GameFrame(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void *DataPtr);
        static void GameStart(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void *DataPtr);
        ....
    };
     
    void CGameApp::GameStart(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void *DataPtr) {
        CGameApp *GameApp = (CGameApp*)pCaller;
        if (Purpose == SM_RENDER) {
            pDevice->SetTransform(D3DTS_VIEW, GameApp->m_camera.GetViewMatrix() );
            GameApp->m_fps = GameApp->m_pFramework->GetFPS() + " fps";
            pDevice->Clear(0, 
                           0, 
                           D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 
                           D3DCOLOR_XRGB(0, 0, 0), 
                           1.0f, 
                           0); 
            pDevice->BeginScene();
            GameApp->m_pTextSprite->Begin(D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE);
     
            GameApp->m_font.Print(g_instructions1.c_str(), 5, 20, D3DCOLOR_XRGB(200, 200, 200), GameApp->m_pTextSprite);
     
            GameApp->m_pTextSprite->End();
            pDevice->EndScene();
            pDevice->Present(0, 0, 0, 0);
        }
        if (Purpose == SM_PROCESS) {
            sUserInput Input = *( (psUserInput)DataPtr);
            if (Input.pPressedKeys[DIK_ESCAPE] ) { 
                GameApp->m_pFramework->LockKey(DIK_ESCAPE); 
                GameApp->m_StateManager.PopAll();
                PostQuitMessage(0); 
            }
            if (Input.pPressedKeys[DIK_SPACE]) {
                GameApp->m_pFramework->LockKey(DIK_SPACE);
                GameApp->m_StateManager.Push(GameApp->GameFrame);
            }
        }
        return;
    }
     
    void CGameApp::GameFrame(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void *DataPtr) {
        CGameApp *GameApp = (CGameApp*)pCaller;
        if (Purpose == SM_RENDER) {
            pDevice->SetTransform(D3DTS_VIEW, GameApp->m_camera.GetViewMatrix() );
            GameApp->m_fps = GameApp->m_pFramework->GetFPS() + " fps";
            pDevice->Clear(0, 
                           0, 
                           D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 
                           D3DCOLOR_XRGB(0, 0, 0), 
                           1.0f, 
                           0); 
            pDevice->BeginScene();
            GameApp->m_pBall->Render(pDevice);
            GameApp->m_pWall->Render(pDevice);
     
            // Display framerate and instructions
            GameApp->m_pTextSprite->Begin(D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE);
     
            GameApp->m_font.Print(GameApp->m_fps.c_str(), 5, 5, D3DCOLOR_XRGB(255, 0, 0), GameApp->m_pTextSprite);
            GameApp->m_font.Print(g_instructions2.c_str(), 5, 20, D3DCOLOR_XRGB(200, 200, 200), GameApp->m_pTextSprite);
     
            GameApp->m_pTextSprite->End();
            pDevice->EndScene();
            pDevice->Present(0, 0, 0, 0);
        }
        if (Purpose == SM_PROCESS) {
            sUserInput Input = *( (psUserInput)DataPtr);
            if (Input.pPressedKeys[DIK_F1] ) {
                GameApp->m_pFramework->LockKey(DIK_F1);
                GameApp->m_pFramework->ToggleFullscreen();
            }
            if (Input.pPressedKeys[DIK_ESCAPE] ) { 
                GameApp->m_pFramework->LockKey(DIK_ESCAPE); 
                GameApp->m_StateManager.Pop();
            }
        }
        return;
    }
    And here is how it is being used...
    Code:
    void CGameApp::OnCreateDevice(LPDIRECT3DDEVICE9 pDevice) {
        m_StateManager.Push(GameStart);
        ....
    }
     
    void CGameApp::OnRenderFrame(LPDIRECT3DDEVICE9 pDevice, float ElapsedTime) {
        m_StateManager.Process(pDevice, this, SM_RENDER);
        return;
    }
     
    void CGameApp::ProcessInput(LPDIRECT3DDEVICE9 pDevice, 
                                long xDelta, 
                                long yDelta, 
                                long zDelta, 
                                bool* pMouseButtons, 
                                bool* pPressedKeys, 
                                float ElapsedTime) { 
        sUserInput Input = { xDelta, yDelta, zDelta, pMouseButtons, pPressedKeys };
        m_StateManager.Process(pDevice, this, SM_PROCESS, (void*)&Input);
        return;
    }
    I think I have all the relavent code listed, but if there is anything else you need please ask and I will post some more.

    I'm not sure why this is not working, any ideas?
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

  2. #2
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    So is your rendering routine being processed? With the parameters you gave it? If it is, then it's really hard to tell you what's wrong with your manager, and could be a whoile number of other issues like camera stuff. Quick test could be to use dx lookat to look at the center of the world with some primitive there.

    >> m_StateManager.Process(pDevice, this, SM_RENDER);

    Does that work? I.e. Process(LPDIRECT3DDEVICE9 pDevice, void* pCaller, UINT Purpose, void* pData) /* ? */

    >> std::vector<pFunction>::iterator StateIter;

    Your use of this is concerning, because of iterator invalidation and such, but the way you use it doesn't seem problematic. You could, instead, just say this

    Code:
    (*States.back())(pDevice, pCaller, Purpose, pData);
    But whatever, you probably have a reason for using it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Finite State Machine
    By ArlexBee-871RBO in forum C++ Programming
    Replies: 8
    Last Post: 07-14-2008, 11:59 AM
  2. Grammar to FSA to C code (Newbie)
    By aybe in forum C Programming
    Replies: 4
    Last Post: 02-29-2008, 02:10 PM
  3. input/switch statement issues
    By peanut in forum C Programming
    Replies: 5
    Last Post: 10-27-2006, 02:58 PM
  4. State manager generic data
    By cboard_member in forum Game Programming
    Replies: 3
    Last Post: 06-06-2006, 10:52 AM
  5. NAQ: Everything you never wanted to know about CPP
    By evildave in forum C Programming
    Replies: 21
    Last Post: 12-12-2005, 10:56 AM