C#

Fools ignore complexity; pragmatists suffer it; experts avoid it; CREATIVES remove it.

Tuesday, November 10, 2009

Generic interface game flow



Question? is that possible to create an architecture, interface based, which allows you programming a game flow independent of his content?

answer: yes!

Note that Minigame_Pinball and Minigame_Pinball_Score are just interface implementations that don't know nothing about the game flow, they are using IGameObj to connect to the flow and returning a condition from FLOW_CONDITIONS, they register themselves and they are allocated only when I need them :) (it's easy to pre-allocate if you want to)

Now, you can copy the code, create your own game class, derive that from IGameCreateObj and implementing your own IGameObj and have fun!!!!



//class MyOwn : public IGameCreateObj<MyOwn>

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <typeinfo>
#include <time.h>

using namespace std;

enum FLOW_CONDITIONS { LOOP = 0, NEXT_FLOW, BACK, NEXT };

class IGameObj
{
public:
virtual void Init() = 0;
virtual FLOW_CONDITIONS Loop() = 0;
virtual void Uninit() = 0;
virtual IGameObj *CreateANew() = 0;

virtual ~IGameObj(){};
};

template<class X>
class IGameCreateObj : public IGameObj
{
public:
//make singleton
static X* GetInstance() { static X x; return &x; }
//able to get a copy
IGameObj *CreateANew() { return new X(); };

virtual ~IGameCreateObj(){};
};

class Minigame_Pinball : public IGameCreateObj<Minigame_Pinball>
{
private:
double timeOut;

public:
void Init() { timeOut = clock(); };
FLOW_CONDITIONS Loop()
{

timeOut += clock()-timeOut;

if (timeOut > 3000)
return NEXT;

cout << "Minigame_Pinball " << timeOut << endl;

return LOOP;
};

void Uninit() {};
};

class Minigame_Pinball_Score : public IGameCreateObj<Minigame_Pinball_Score>
{
public:
void Init() {};
FLOW_CONDITIONS Loop() { return LOOP;};
void Uninit() {};
};

struct FlowCondition
{
IGameObj *obj1;
FLOW_CONDITIONS fc;
IGameObj *obj2;
};

class IGameFlow
{
public:
virtual bool Loop() = 0;
};

class GameFlow : public IGameFlow
{
private:
vector<const FlowCondition* const> _list;

IGameObj *_currentObj;

IGameObj *AllocType( IGameObj *obj_info )
{
IGameObj *mg = NULL;
mg = obj_info->CreateANew();
return mg;
}

FlowCondition *SearchCondition( FLOW_CONDITIONS fc )
{
vector<const FlowCondition* const>::iterator it;
for( it = _list.begin(); it != _list.end(); ++it )
if ((*it)->fc == fc) return (FlowCondition *)*it;
return NULL;
};

public:
GameFlow() : _currentObj(NULL) {};

void RegisterCondition(IGameObj *obj1, const FLOW_CONDITIONS fc, IGameObj *obj2 )
{
FlowCondition *p = new FlowCondition();
p->fc = fc;
p->obj1 = obj1;
p->obj2 = obj2;
_list.push_back( p );

if (_currentObj == NULL)
{
_currentObj = AllocType(obj1);
_currentObj->Init();
}
return;
}

virtual ~GameFlow()
{
vector<const FlowCondition* const>::iterator it;
for( it = _list.begin(); it != _list.end(); ++it )
delete *it;

delete _currentObj;
}

bool Loop()
{
FLOW_CONDITIONS fc = _currentObj->Loop();
if (fc==NEXT_FLOW) return false;

FlowCondition *tmp = SearchCondition( fc );
if (tmp != NULL)
{
_currentObj->Uninit();
delete _currentObj;
_currentObj = AllocType(tmp->obj2);
_currentObj->Init();
}

return true;
}
};

class GameFlowManager
{
private:
vector<const IGameFlow* const> _list;

IGameFlow* _gFlowCurrent;

public:
GameFlowManager() : _gFlowCurrent(NULL) {};

void RegisterFlow(IGameFlow *gflow)
{
if (_gFlowCurrent==NULL) _gFlowCurrent = gflow;
_list.push_back( gflow );
return;
}

void Loop()
{
while(_gFlowCurrent->Loop())
{
}
}
};


int _tmain(int argc, _TCHAR* argv[])
{
GameFlow minigameFlow;
minigameFlow.RegisterCondition( Minigame_Pinball::GetInstance(), NEXT, Minigame_Pinball_Score::GetInstance());
minigameFlow.RegisterCondition( Minigame_Pinball_Score::GetInstance(), BACK, Minigame_Pinball::GetInstance());
minigameFlow.RegisterCondition( Minigame_Pinball_Score::GetInstance(), NEXT_FLOW, NULL );

GameFlowManager game;
game.RegisterFlow( (IGameFlow*)&minigameFlow );
game.Loop();

return 0;
}


Nowadays, I'm working as director of pre-production so "officially" I do not write code, anyway, I hope it can help someone :)

3 comments:

Anonymous said...

Niсe answеr back in гeturn of this query
with genuine arguments and telling the whole thing about that.


My blog post; Runnersoul.com

Anonymous said...

You can definitely seе your skills іn the work you ωгite.
The аrena hopeѕ for more passiοnate ωrіteгs
like уou who aren't afraid to mention how they believe. At all times go after your heart.

Also visit my web blog - click through The following website

Anonymous said...

I like thе helpful info yоu рrovide in your articles.

I will booκmark your blog and check agаin hеre frequently.
I аm quite certain I will lеаrn lots of nеw ѕtuff right here!
Best οf luck for the next!

my web ѕite visit the following website page