School Assignment? Project Due Tomorrow? Chat LIVE With A Programming Expert!

Welcome to Dream.In.Code
Become an Expert!

Join 307,109 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 2,004 people online right now. Registration is fast and FREE... Join Now!




Organizing and accessing engine subsystems

 

Organizing and accessing engine subsystems

mastersmith98

29 Oct, 2009 - 05:48 PM
Post #1

New D.I.C Head
*

Joined: 22 Dec, 2008
Posts: 38



Thanked: 1 times
My Contributions
After working on several projects I've recently just come to the realization that it might be a good idea to create a reusable set of classes and code so that I'm not rewriting base level code for each new game project I work on. Unfortunately, I quickly found out why I never did this in the first place. Finding an effective way to organize and grant access to subsystems of my code (such as a rendering class) is becoming a real pain.

What I have set up right now is a base engine class, which manages and contains all the subsystems of the program, with each subsystem delegated towards a specific operation in the framework of the game. At the moment I have a renderer class, which obviously handles rendering duties, and a gamestate manager, which manages the different gamestates loaded into memory.

The subsystems are represented as singleton classes, so that they can be used in any code, using the same instance, that includes their respective header file. This is where my problem arises. Having to call Class::Instance()->MemberFunction(); for any operation with that class is very tedious and the idea of having a singleton and a central point of access seems lazy. There should be a better alternative.

People at the gamedev.net chat suggested using a design pattern called dependency injection. It sounds like an interesting solution, but I just wanted a second opinion from the monocle toting elite of [insert forum name here]. tongue.gif

Here are some code examples to give you guys a better understanding of what I have so far.

GameEngine.h
CODE
//=============================================================================
//
// CGameEngine used as a manager for all the major subsystems of the game
//
//=============================================================================

#ifndef GAME_ENGINE_H
#define GAME_ENGINE_H

#include "SystemDefs.h"

class CGameEngine
{
    static CGameEngine* m_pInstance;

    CStateManager* m_pStateManager;
    CRenderer* m_pRenderer;

    bool m_bRunning;

public:
    ~CGameEngine();

    static CGameEngine* Instance( void );

    bool Init( void ); //initial engine startup
    void CleanUp( void ); //engine destruction

    //loop functions
    void HandleEvents( void ); //checks for keyboard and mouse input
    void Update( void ); //allows objects and systems to update their states
    void Render( void ); //draws everything to the screen

    bool IsRunning( void ) { return m_bRunning; } //Determines whether program quits

protected:
    CGameEngine();

private:
    bool InitSDL( void );
    void CleanUpSDL( void );
};

#endif; //GAME_ENGINE_H


GameEngine.cpp
CODE
//=============================================================================
//
// CGameEngine used as a manager for all the major subsystems of the game
//
//=============================================================================

#include "GameEngine.h"
#include "Render.h"
#include "GameState.h"
#include "SDL.h"
#include <assert.h>

//=============================================================================
// Static variable Initialization
//=============================================================================
CGameEngine* CGameEngine::m_pInstance = NULL;



//=============================================================================
// Constructor
//=============================================================================
CGameEngine::CGameEngine( void )
{
    m_bRunning = true;
}

//=============================================================================
// Destructor
//=============================================================================
CGameEngine::~CGameEngine( void )
{

}

//=============================================================================
//
//=============================================================================
CGameEngine* CGameEngine::Instance( void )
{
    if( !m_pInstance )
        m_pInstance = new CGameEngine;

    return m_pInstance;
}

//=============================================================================
// Initializes all the subsystems
//=============================================================================
bool CGameEngine::Init( void )
{
    //Start up SDL
    if( !InitSDL() )
        return false;

    //Initialize the state manager
    if( !CGameStateManager::Instance()->Init() )
        return false;

    //Initialize the Renderer
    if( !CRenderer::Instance()->Init() )
        return false;

    //Change the caption
    SDL_WM_SetCaption( "SDL Base", NULL );

    return true;
}

//=============================================================================
// Cleans up all the subsystems
//=============================================================================
void CGameEngine::CleanUp( void )
{
    //Clean up Gamestate manager
    CGameStateManager::Instance()->CleanUp();
    
    //Clean up the Renderer
    CRenderer::Instance()->CleanUp();

    CleanUpSDL();
}

//=============================================================================
// Handles the events (keyboard and mouse input, system events, etc) of the game
//=============================================================================
void CGameEngine::HandleEvents( void )
{
    CGameStateManager::Instance()->GameState()->HandleEvents();
}

//=============================================================================
// Updates the subsystems
//=============================================================================
void CGameEngine::Update( void )
{
    CGameStateManager::Instance()->GameState()->Update();
}

//=============================================================================
// Render's everything to the screen
//=============================================================================
void CGameEngine::Render( void )
{
    CGameStateManager::Instance()->GameState()->Render();
}

//=============================================================================
//
//=============================================================================
bool CGameEngine::InitSDL( void )
{
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
        return false;

    return true;
}

void CGameEngine::CleanUpSDL( void )
{
    SDL_Quit();
}


GameState.h
CODE
//=============================================================================
//
// Manages and contains game states
//
//=============================================================================

#ifndef GAME_STATE_H
#define GAME_STATE_H

#include "SystemDefs.h"
#include <string>
#include <map>

//interface class for all future implementations of the gamestate
class IGameState
{
public:
    virtual ~IGameState( void ) { };

    virtual bool Init( void ) = 0;
    virtual void CleanUp( void ) = 0;

    virtual void HandleEvents( void ) = 0;
    virtual void Update( void ) = 0;
    virtual void Render( void ) = 0;
};

class CGameState : public IGameState
{
public:
    virtual bool Init( void );
    virtual void CleanUp( void );

    virtual void HandleEvents( void );
    virtual void Update( void );
    virtual void Render( void );
};

class CGameStateManager
{
    static CGameStateManager* m_pInstance;
    std::map<std::string, IGameState*> m_mapGameState;
    IGameState* m_pCurrGameState;

public:
    ~CGameStateManager( void );

    static CGameStateManager* Instance( void );

    bool Init( void );
    void CleanUp( void );

    void AddGameState( std::string strName, IGameState* pState );
    void RemoveGameState( std::string strName );

    bool SetGameState( std::string strName ); //sets the currently active game state
    IGameState* GameState( void ); //returns the current game state

protected:
    CGameStateManager( void );
};

#endif; //GAME_STATE_H


GameState.cpp
CODE
//=============================================================================
//
// Manages and contains game states
//
//=============================================================================

#include "GameState.h"
#include "Render.h"
#include "SDL.h"
#include <assert.h>

//=============================================================================
// Static variable initialization
//=============================================================================
CGameStateManager* CGameStateManager::m_pInstance = NULL;



//=============================================================================
// Constructor
//=============================================================================
CGameStateManager::CGameStateManager( void )
{
    m_pCurrGameState = NULL;
}

//=============================================================================
// Destuctor
//=============================================================================
CGameStateManager::~CGameStateManager( void )
{

}

//=============================================================================
// Initialize
//=============================================================================
bool CGameStateManager::Init( void )
{
    return true;
}

//=============================================================================
// Cleanup
//=============================================================================
void CGameStateManager::CleanUp( void )
{

}

//=============================================================================
// Instance
//=============================================================================
CGameStateManager* CGameStateManager::Instance( void )
{
    if( !m_pInstance )
        m_pInstance = new CGameStateManager;

    return m_pInstance;
}

//=============================================================================
//
//=============================================================================
void CGameStateManager::AddGameState( std::string strName, IGameState* pState )
{
    //a game state should never be null
    assert( pState );

    m_mapGameState.insert( std::pair<std::string,IGameState*>( strName, pState ) );
}

//=============================================================================
//
//=============================================================================
void CGameStateManager::RemoveGameState( std::string strName )
{
    std::map<std::string,IGameState*>::iterator it;

    it = m_mapGameState.find( strName );

    //again, game state should not be null
    assert( it->second );

    //allow the game state to clean up allocated memory
    it->second->CleanUp();

    m_mapGameState.erase( it );
}

//=============================================================================
//
//=============================================================================
bool CGameStateManager::SetGameState( std::string strName )
{
    std::map<std::string, IGameState*>::iterator it;

    it = m_mapGameState.find( strName );

    //if the map wasn't found or it is null
    if( !it->second )
        return false;

    m_pCurrGameState = it->second;

    //allow the game state to init its self
    if( !m_pCurrGameState->Init() )
        return false;

    return true;
}

//=============================================================================
//
//=============================================================================
IGameState* CGameStateManager::GameState( void )
{
    return m_pCurrGameState;
}



//=============================================================================
//
// CGameState
//
//=============================================================================

//=============================================================================
//
//=============================================================================
bool CGameState::Init( void )
{
    return true;
}

//=============================================================================
//
//=============================================================================
void CGameState::CleanUp( void )
{

}

//=============================================================================
//
//=============================================================================
void CGameState::HandleEvents( void )
{
    SDL_Event Event;

    while( SDL_PollEvent(&Event) )
    {
    }
}

//=============================================================================
//
//=============================================================================
void CGameState::Update( void )
{

}

//=============================================================================
//
//=============================================================================
void CGameState::Render( void )
{
    CRenderer::Instance()->UpdateScreen();
}


render.h
CODE
//=============================================================================
//
// Main renderer for the game
//
//=============================================================================

#ifndef RENDER_H
#define RENDER_H

#include "SystemDefs.h"
#include "SDL.h"

class CRenderer
{
    static CRenderer* m_pInstance;

    SDL_Surface* m_pScreen;

public:
    ~CRenderer( void );

    static CRenderer* Instance( void );

    bool Init( void );
    void CleanUp( void );

    void UpdateScreen( void );

    void ApplySurface( SDL_Surface* pSurface, int x, int y, SDL_Rect *rClip = NULL );

protected:
    CRenderer( void );
};

#endif; //RENDER_H


render.cpp
CODE
//=============================================================================
//
// Main renderer for the game
//
//=============================================================================

#include "Render.h"
#include "SDL.h"

//=============================================================================
// Static variable initialization
//=============================================================================
CRenderer* CRenderer::m_pInstance = NULL;



//=============================================================================
// Constructor
//=============================================================================
CRenderer::CRenderer( void )
{

}

//=============================================================================
// Destructor
//=============================================================================
CRenderer::~CRenderer( void )
{

}

//=============================================================================
//
//=============================================================================
CRenderer* CRenderer::Instance( void )
{
    if( !m_pInstance )
        m_pInstance = new CRenderer;

    return m_pInstance;
}

//=============================================================================
// Sets up the screen for drawing
//=============================================================================
bool CRenderer::Init( void )
{
    m_pScreen = SDL_SetVideoMode( 800, 600, 32, SDL_SWSURFACE );

    if( !m_pScreen )
        return false;

    return true;
}

//=============================================================================
// CleanUp
//=============================================================================
void CRenderer::CleanUp( void )
{

}

//=============================================================================
// Renders everything to the screen
//=============================================================================
void CRenderer::UpdateScreen( void )
{
    //Flips the surface to the screen
    SDL_Flip( m_pScreen );
}
//=============================================================================
// Applys a surface to the screen
//=============================================================================
void CRenderer::ApplySurface( SDL_Surface* pSurface, int x, int y, SDL_Rect* rClip )
{
    //Transfer x, y data to SDL_Rect for screen offsets
    SDL_Rect rOffset;

    rOffset.x = x;
    rOffset.y = y;

    SDL_BlitSurface( pSurface, rClip, m_pScreen, &rOffset );    
}



main.cpp
CODE
#include "SDL.h"
#include "SDL_TTF.h"
#include "SDL_Mixer.h"

#include "GameEngine.h"
#include "GameState.h"

CGameEngine* pEngine;

int main( int argc, char* args[] )
{
    pEngine = CGameEngine::Instance();

    if( !pEngine || !pEngine->Init() )
        return 1;

    CGameState* p = new CGameState;
    CGameStateManager::Instance()->AddGameState( "BaseGameState", p );
    CGameStateManager::Instance()->SetGameState( "BaseGameState" );

    //main looop
    while( pEngine->IsRunning() )
    {
        pEngine->HandleEvents();
        pEngine->Update();
        pEngine->Render();
    }

    //clean up and quit
    pEngine->CleanUp();

    return 0;
}


I know this is a broad and general question, but any help or suggestions on where to get help would be much appreciated.

User is offlineProfile CardPM
+Quote Post

Fast ReplyReply to this topicStart new topic

Time is now: 11/21/09 12:54PM

Live Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month