Hi JTK,
My condolences to you.
To kick off the discussion, let me say that I'm not a hardcore paradigm guy. I intermix multiple programming paradigms and patterns to achieve goals. Components can use OOP, and OOP can use Procedural Functions. So for me, there is no `correct` way, I'm just looking for one that is flexible, easy-on-the-eyes, and gets the job done. The DOSP project is open-source, and its my desire for the Engine Framework and Scripts to be easy for new C++ programmers to digest. C++ Gurus can tweak to their hearts content.
I sorta stumbled into Entity/Component Model by accident while developing my 100th iteration of 3D GUI. My GUI utilized event handling, messaging, and process optimizations that I figured all Game Entities could use. At that time, I thought I had come up with a completely new concept. I called it Interactive-centric design. I later discovered that the concept already had a name and was adopted by some commercial development houses as the Entity Component Model.
Messaging is key and I was under the impression Entity Components implement the Observer Pattern. Even if its not, that is the approach I'm going to use. I'm looking into
Signals and slots Implementation. As far as can tell Entity Components for Games are not directly byproduct of CBSE.
I started to write S3GP's Components System today and I have to say that I'm excited about it. Components will make the Engine Framework way easier to manage/modify and simplify the process of creating various Game Entities. This puts S3GP one step closure a professional engine design in my opinion. I'm designing my Components based on the following paradigm definitions:
* Entities, which are just global unique IDs (usually implemented as integers for obvious reasons, but they can be anything that can uniquely identify each one).
* Components, which are chunks of data (equivalent to structures in C/C++ like languages, or classes with no methods in languages like Java that force OOP).
* Systems, which drive the whole program. These are normal OOP classes. Each system ideally operates on all components of its type, for example: the Render System will probably operate mainly on Render Components (of course this is just ideal, as you'd probably have some other components to take into consideration, like a Position, or Animation, or whatever).
I'm rewriting all of the Engine Framework to use Components. Here is my current untested work in progress:
Component Declarations
namespace Component{
//Component Parameter
class Parameter{
public:
int Type; //{VALUE,PROPERTY,VARIABLE,SCRIPT}
string Key;
string Value;
Parameter(int type, string key, string value);
~Parameter(void);
};
//Component Messaging
class Message {
public:
void* Receiver;
int Type;
int ID; //message identifier
int ParameterCount;
map<int, Parameter*> ParameterMap;
map<int, Parameter*>::iterator ParameterMapIterator;
int State;
Message(void);
~Message(void);
static Message *Create(int type);
static void Destroy(Message *instance);
void Insert(int type, string key, string value);
void Insert(Parameter ¶meter);
Message *Copy(void);
};
//Component Object Instance Base Class
class Object{
public:
map<int, Parameter*> ParameterMap;
map<int, Parameter*>::iterator ParameterMapIterator;
int EntityID;
int State;
virtual void Start(void) =0;
virtual void Update(void) =0;
virtual void Stop(void) =0;
virtual void MessageProcess(void) =0;
};
//Component Object Manager Base Class
class Manager{
public:
string Name;
string Description;
//System Reference
System* System;
virtual list<Component::Object*> ActiveList;
virtual list<Component::Object*>::iterator ActiveListIterator;
virtual queue<Component::Object*> InactiveQueue;
//Component Methods
Object* ComponentCreate(void)=0;
void ComponentDelete(Object* instance)=0;
};
//Component System Base Class
class System{
public:
string Name;
string Description;
list<Component::Manager*> ComponentManagerList;
//Component Manager Methods
Component::Manager* ComponentManagerCreate(void);
};
namespace Entity{
//Component Entity Instance Class Container
class Object{
public:
int ID;
int SimulationID;
//Component Object List
list<Component::Object*> ComponentList;
// constructor/destructor
Entity(int ID);
virtual ~Entity();
};
//Compenent Entity Manager Class
class Manager{
public:
ResourceManager *EntityResource;
//Entity Methods
int EntityCreate(void);
void EntityDelete(int entityID);
//Component Object Methods
void ComponentAdd(Component::Object* object, list<Parameter*> parameterlist);
void ComponentRemove(Component::Object* object);
void ComponentRemoveAll(void);
void ComponentUpdate(Component::Object* object);
void ComponentUpdateAll(void);
//Message Methods
void MessageProcess(void); // echoes to all attached components
};
}
}
Systems Component Class Declarations
class RenderSystem: public Component::System{
class SpriteComponentManager: public Component::Manager{
};
class SpriteComponent: public Component::Object{
};
class MeshComponentManager: public Component::Manager{
};
class MeshComponent: public Component::Object{
};
class TerrainComponentManager: public Component::Manager{
};
class TerrainComponent: public Component::Object{
};
class BSPComponentManager: public Component::Manager{
};
class BSPComponent: public Component::Object{
};
};
class AudioSystem: public Component::System{
class MusicComponentManager: public Component::Manager{
};
class MusicComponent: public Component::Object{
};
class SoundComponentManager: public Component::Manager{
};
class SoundComponent: public Component::Object{
};
class AcousticComponentManager: public Component::Manager{
};
class AcousticComponent: public Component::Object{
};
class ParticleComponentManager: public Component::Manager{
};
class ParticleComponent: public Component::Object{
};
};
class PlayerEntityManager: public Component::Entity::Manager{
};
class PlayerEntity: public Component::Entity::Object{
);
class BotEntityManager: public Component::Entity::Manager{
};
class BotEntity: public Component::Entity::Object{
};
Framework Construction
//Create Framework Systems
RenderSystem *OgreRenderSystem = new RenderSystem;
AudioSystem *MoodsterAudioSystem = new AudioSystem;
//Create Framework Systems Component Managers
RenderSystem::MeshComponentManager *OgreMeshComponentManager = OgreRenderSystem->ComponentManagerCreate();
AudioSystem::MusicComponentManager *MoodsterMusicComponentManager = MoodsterAudioSystem->ComponentManagerCreate();
//Create Game Entity Manager
PlayerEntityManager *CombatantEntityManager = new PlayerEntityManager;
//Create Game Entity Instance
int TechlordID = CombatantEntityManager->EntityCreate();
//Create Framework Component Instances
RenderSystem::MeshComponent *OgreMeshComponent = OgreMeshComponentManager->ComponentCreate();
AudioSystem::MusicComponent *MoodsterMusicComponent = MoodsterMusicComponentManager->ComponentCreate();
//Add Components to Entity Instance
CombatantEntityManager->ComponentAdd(TechlordID,OgreMeshComponent);
CombatantEntityManager->ComponentAdd(TechlordID,MoodsterMusicComponent);
//Modify Component Data & Logic
OgreMeshComponent->ParameterAdd(new Parameter(0,"Name","MyCube"));
OgreMeshComponent->Load("cube.x");