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].

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.