Ok mir war langweilig und ich hab ein SingeltonTemplate geschrieben mit dem man aus jede Klasse oder Variable ein Singleton machen kann ohne diese zu verändern. Man könnte sogar das IrrlichtDevice zu einem ingelton machen
Das Template:
Code:
#include <iostream>
#include <irrlicht.h>
#include <assert.h>
template<class A>
class SingeltonTemplate
{
public:
SingeltonTemplate(A* i = NULL)
{
if (RefCounter == 0)
{
Instance = i;
}
//if (Instance == NULL) //try calling standard constructor...not a good idea
//Instance = new A();
assert(Instance != NULL);
if (AutoRemove)
RefCounter++;
}
SingeltonTemplate(const SingeltonTemplate<A>& singelton)
{
if (Instance == NULL) //try calling standard constructor
Instance = new A();
assert(Instance != NULL);
if (AutoRemove)
RefCounter++;
}
~SingeltonTemplate(void)
{
if (AutoRemove && Instance)
RefCounter--;
if (RefCounter == 0)
{
delete Instance;
Instance = NULL;
}
assert(RefCounter >= 0);
}
A* operator->(void)
{
return Instance;
}
A* operator*(void)
{
return Instance;
}
const A* operator->(void) const
{
return Instance;
}
const A* operator*(void) const
{
return Instance;
}
static void TurnAutoRemoveOff(void)
{
AutoRemove = false;
}
void Destroy(void)
{
AutoRemove = true;
if (Instance)
delete Instance;
Instance = NULL;
RefCounter = 0;
}
const bool Valid(void) const
{
if ((RefCounter > 0 || !AutoRemove) && Instance)
return true;
return false;
}
static int GetRefCount(void)
{
return RefCounter;
}
SingeltonTemplate& operator=(const SingeltonTemplate<A>& singelton)
{
//dunno but i think i don't have to grab the pointer here
}
protected:
static A* Instance;
static int RefCounter;
static bool AutoRemove;
};
template<class A> A* SingeltonTemplate<A>::Instance = NULL;
template<class A> int SingeltonTemplate<A>::RefCounter = 0;
template<class A> bool SingeltonTemplate<A>::AutoRemove = true;
Und hier ein Beispiel. Ich weiß das ich da c und c++ dinge vermische und es eigentlich keinen sinn macht aber das hier ist auch ein beispiel für das singelton und nicht zum lernen von designs gedacht.
Code:
class CEntity;
typedef void (*UpdatePointer)(int timeMs, CEntity& entity);
typedef void (*InitPointer)(CEntity& entity);
typedef void (*TimeEventPointer)(void);
void StandardEntityUpdate(int timeMs, CEntity& entity);
class CEntityData
{
public:
virtual ~CEntityData(void)
{
}
};
class CEntity
{
public:
CEntity(int id, const irr::c8* type) : EntityID(id), EntityType(type), UpdateEntity(&StandardEntityUpdate), Data(NULL)
{
}
CEntity(const CEntity& entity) : EntityID(entity.getEntityID()), EntityType(entity.EntityType), UpdateEntity(entity.UpdateEntity), Data(NULL)
{
}
CEntity& operator=(const CEntity& entity)
{
EntityID = entity.getEntityID();
UpdateEntity = entity.UpdateEntity;
Data = entity.Data;
EntityType = entity.EntityType;
return *this;
}
const int& getEntityID(void) const
{
return EntityID;
}
void setEntityData(CEntityData* data)
{
Data = data;
}
CEntityData* getEntityData(void)
{
return Data;
}
const CEntityData* getEntityData(void) const
{
return Data;
}
UpdatePointer UpdateEntity;
InitPointer Destructor;
protected:
int EntityID;
CEntityData* Data;
irr::core::stringc EntityType;
};
void StandardEntityUpdate(int timeMs, CEntity& entity)
{
std::cout<<"Entity["<<entity.getEntityID()<<"] Time: "<<timeMs<<std::endl;
}
class CGameEngine
{
public:
CGameEngine(void)
{
LastEntityID = 0;
Device = irr::createDevice(irr::video::EDT_OPENGL);
}
~CGameEngine(void)
{
Device->drop();
}
void RegisterInit(const irr::c8* name, InitPointer init, InitPointer desctruct)
{
for (int i=0;i<InitEntities.size();i++)
{
if (InitEntities[i].Name == name)
{
InitEntities[i].Init = init;
return;
}
}
InitEntities.push_back(EntityTemplate(name, init, desctruct));
}
int addEntity(const irr::c8* name = NULL)
{
std::cout<<"Added Entity"<<std::endl;
Entities.push_back(CEntity(LastEntityID++, name));
for (int i=0;i<InitEntities.size();i++)
{
if (InitEntities[i].Name == name)
{
InitEntities[i].Init(Entities[Entities.size()-1]);
Entities[Entities.size()-1].Destructor = InitEntities[i].Destruct;
}
}
return Entities[Entities.size()-1].getEntityID();
}
void removeEntity(int i)
{
if (Entities.size() > i)
{
Entities[i].Destructor(Entities[i]);
Entities.erase(i);
}
}
void addTimeEvent(int timeMs, TimeEventPointer event)
{
TimeEvents.push_back(TimeEvent(Device->getTimer()->getTime()+timeMs, event));
TimeEvents.sort();
}
void Run(void)
{
while (Device->run())
{
//update entities
for (int i=0;i<Entities.size();i++)
Entities[i].UpdateEntity(Device->getTimer()->getTime(), Entities[i]);
//trigger Events
while(TimeEvents.size() > 0 && TimeEvents[0].TimeMs < Device->getTimer()->getTime())
{
TimeEvents[0].Event();
TimeEvents.erase(0);
}
//Render stuff
Device->getVideoDriver()->beginScene(true, true, irr::video::SColor(255,0,0,255));
Device->getSceneManager()->drawAll();
Device->getGUIEnvironment()->drawAll();
Device->getVideoDriver()->endScene();
}
Device->closeDevice();
}
int getTime(void) const
{
return Device->getTimer()->getTime();
}
irr::IrrlichtDevice* getDevice(void)
{
return Device;
}
protected:
int LastEntityID;
irr::core::array<CEntity> Entities;
class TimeEvent
{
public:
TimeEvent(int timeMs, TimeEventPointer event) : TimeMs(timeMs), Event(event)
{
}
TimeEvent(const TimeEvent& tmp) : TimeMs(tmp.TimeMs), Event(tmp.Event)
{
}
TimeEvent& operator=(const TimeEvent& tmp)
{
TimeMs = tmp.TimeMs;
Event = tmp.Event;
return *this;
}
bool operator<(const TimeEvent& tmp)
{
return TimeMs < tmp.TimeMs;
}
int TimeMs;
TimeEventPointer Event;
};
class EntityTemplate
{
public:
EntityTemplate(const irr::c8* name, InitPointer init, InitPointer destruct)
{
Name = name;
Init = init;
Destruct = destruct;
}
EntityTemplate(const EntityTemplate& temp)
{
Name = temp.Name;
Init = temp.Init;
Destruct = temp.Destruct;
}
EntityTemplate& operator=(const EntityTemplate& temp)
{
Name = temp.Name;
Init = temp.Init;
Destruct = temp.Destruct;
return *this;
}
irr::core::stringc Name;
InitPointer Init;
InitPointer Destruct;
};
irr::core::array<EntityTemplate> InitEntities;
irr::core::array<TimeEvent> TimeEvents;
//irrlicht
irr::IrrlichtDevice* Device;
};
typedef SingeltonTemplate<CGameEngine> GameEngine;
class CPlayerData : public CEntityData
{
public:
CPlayerData(void)
{
Health = 0;
Node = NULL;
Cam = NULL;
}
~CPlayerData(void)
{
if (Node)
{
Node->remove();
Node->drop();
}
if (Cam)
{
Cam->remove();
Cam->drop();
}
Node = NULL;
Cam = NULL;
}
irr::scene::ISceneNode* Node;
irr::scene::ICameraSceneNode* Cam;
int Health;
};
void UpdatePlayer(int timeMs, CEntity& entity)
{
std::cout<<"Update Player ["<<entity.getEntityID()<<"] Time: "<<timeMs<<std::endl;
}
void InitPlayer(CEntity& entity)
{
std::cout<<"Init Player"<<std::endl;
CPlayerData* data = new CPlayerData;
entity.setEntityData(data);
entity.UpdateEntity = &UpdatePlayer;
//load mesh
GameEngine engine;
data->Node = engine->getDevice()->getSceneManager()->addAnimatedMeshSceneNode(engine->getDevice()->getSceneManager()->getMesh("faerie.md2"));
data->Node->grab();
data->Cam = engine->getDevice()->getSceneManager()->addCameraSceneNodeFPS();
data->Cam->grab();
}
void DeInitPlayer(CEntity& entity)
{
delete entity.getEntityData();
}
void RemovePlayerEvent(void)
{
GameEngine engine;
engine->removeEntity(0);
}
void TestEvent(void)
{
GameEngine engine;
std::cout<<"Test Event: "<<engine->getTime()<<std::endl;
}
int main(void)
{
GameEngine engine(new CGameEngine);
engine->addTimeEvent(10000, &RemovePlayerEvent);
engine->addTimeEvent(500, &TestEvent);
engine->RegisterInit("player", &InitPlayer, &DeInitPlayer);
engine->addEntity("player");
engine->Run();
return 0;
}