2009년 11월 26일 목요일

game state manager

gamestate.h



#ifndef GAMESTATE_H
#define GAMESTATE_H

#include "gameengine.h"

class CGameState
{
public:
virtual void Init() = 0;
virtual void Cleanup() = 0;

virtual void Pause() = 0;
virtual void Resume() = 0;

virtual void HandleEvents(CGameEngine* game) = 0;
virtual void Update(CGameEngine* game) = 0;
virtual void Draw(CGameEngine* game) = 0;

void ChangeState(CGameEngine* game, CGameState* state) {
game->ChangeState(state);
}

protected:
CGameState() { }
};

#endif

gameengine.h



#ifndef GAMEENGINE_H
#define GAMEENGINE_H

#include "SDL.h"

#include ''
using namespace std;

class CGameState;

class CGameEngine
{
public:

void Init(const char* title, int width=640, int height=480,
     int bpp=0, bool fullscreen=false);
void Cleanup();

void ChangeState(CGameState* state);
void PushState(CGameState* state);
void PopState();

void HandleEvents();
void Update();
void Draw();

bool Running() { return m_running; }
void Quit() { m_running = false; }

SDL_Surface* screen;

private:
// the stack of states
vector states;

bool m_running;
bool m_fullscreen;
};

#endif

gameengine.cpp


#include ''

#include "SDL.h"
#include "gameengine.h"
#include "gamestate.h"

void CGameEngine::Init(const char* title, int width, int height, 
int bpp, bool fullscreen)
{
int flags = 0;

// initialize SDL
SDL_Init(SDL_INIT_VIDEO);

// set the title bar text
SDL_WM_SetCaption(title, title);

if ( fullscreen ) {
flags = SDL_FULLSCREEN;
}

// create the screen surface
screen = SDL_SetVideoMode(width, height, bpp, flags);

m_fullscreen = fullscreen;
m_running = true;

printf("CGameEngine Init\n");
}

void CGameEngine::Cleanup()
{
// cleanup the all states
while ( !states.empty() ) {
states.back()->Cleanup();
states.pop_back();
}

// switch back to windowed mode so other 
// programs won't get accidentally resized
if ( m_fullscreen ) {
screen = SDL_SetVideoMode(640, 480, 0, 0);
}

printf("CGameEngine Cleanup\n");

// shutdown SDL
SDL_Quit();
}

void CGameEngine::ChangeState(CGameState* state) 
{
// cleanup the current state
if ( !states.empty() ) {
states.back()->Cleanup();
states.pop_back();
}

// store and init the new state
states.push_back(state);
states.back()->Init();
}

void CGameEngine::PushState(CGameState* state)
{
// pause current state
if ( !states.empty() ) {
states.back()->Pause();
}

// store and init the new state
states.push_back(state);
states.back()->Init();
}

void CGameEngine::PopState()
{
// cleanup the current state
if ( !states.empty() ) {
states.back()->Cleanup();
states.pop_back();
}

// resume previous state
if ( !states.empty() ) {
states.back()->Resume();
}
}


void CGameEngine::HandleEvents() 
{
// let the state handle events
states.back()->HandleEvents(this);
}

void CGameEngine::Update() 
{
// let the state update the game
states.back()->Update(this);
}

void CGameEngine::Draw() 
{
// let the state draw the screen
states.back()->Draw(this);
}

introstate.h


#ifndef INTROSTATE_H
#define INTROSTATE_H

#include "SDL.h"
#include "gamestate.h"

class CIntroState : public CGameState
{
public:
void Init();
void Cleanup();

void Pause();
void Resume();

void HandleEvents(CGameEngine* game);
void Update(CGameEngine* game);
void Draw(CGameEngine* game);

static CIntroState* Instance() {
return &m_IntroState;
}

protected:
CIntroState() { }

private:
static CIntroState m_IntroState;

SDL_Surface* bg;
SDL_Surface* fader;
int alpha;
};

#endif

introstate.cpp


#include

#include "SDL.h"
#include "gameengine.h"
#include "gamestate.h"
#include "introstate.h"
#include "playstate.h"

CIntroState CIntroState::m_IntroState;

void CIntroState::Init()
{
SDL_Surface* temp = SDL_LoadBMP("intro.bmp");

bg = SDL_DisplayFormat(temp);

SDL_FreeSurface(temp);

// create the fader surface like the background with alpha
fader = SDL_CreateRGBSurface( SDL_SRCALPHA, bg->w, bg->h, 
 bg->format->BitsPerPixel, 
 bg->format->Rmask, bg->format->Gmask, 
 bg->format->Bmask, bg->format->Amask );

// fill the fader surface with black
SDL_FillRect (fader, NULL, SDL_MapRGB (bg->format, 0, 0, 0)) ;

// start off opaque
alpha = 255;

SDL_SetAlpha(fader, SDL_SRCALPHA, alpha);

printf("CIntroState Init\n");
}

void CIntroState::Cleanup()
{
SDL_FreeSurface(bg);
SDL_FreeSurface(fader);

printf("CIntroState Cleanup\n");
}

void CIntroState::Pause()
{
printf("CIntroState Pause\n");
}

void CIntroState::Resume()
{
printf("CIntroState Resume\n");
}

void CIntroState::HandleEvents(CGameEngine* game)
{
SDL_Event event;

if (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
game->Quit();
break;

case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_SPACE:
game->ChangeState( CPlayState::Instance() );
break;

case SDLK_ESCAPE:
game->Quit();
break;
}
break;
}
}
}

void CIntroState::Update(CGameEngine* game) 
{
alpha--;

if (alpha < 0)
alpha = 0;

SDL_SetAlpha(fader, SDL_SRCALPHA, alpha);
}

void CIntroState::Draw(CGameEngine* game) 
{
SDL_BlitSurface(bg, NULL, game->screen, NULL);

// no need to blit if it's transparent
if ( alpha != 0 )
SDL_BlitSurface(fader, NULL, game->screen, NULL);

SDL_UpdateRect(game->screen, 0, 0, 0, 0);
}

main.cpp


#include "gameengine.h"
#include "introstate.h"

int main ( int argc, char *argv[] )
{
CGameEngine game;

// initialize the engine
game.Init( "Engine Test v1.0" );

// load the intro
game.ChangeState( CIntroState::Instance() );

// main loop
while ( game.Running() )
{
game.HandleEvents();
game.Update();
game.Draw();
}

// cleanup the engine
game.Cleanup();

return 0;
}









댓글 없음:

댓글 쓰기