There is a Component Pool for each component and that holds every single component of that type.
Each System keeps track of each of the entities that is registered for it and then on update the system loops through all the entities getting the components that it needs for that entity and performing the actions on it.
This new way of doing things, having systems work on their own will give me the opportunity to add thread pools once that is necessary. This will allow me to use worker threads for sections of entities registered for the system.
So that is the general usage of the Systems and Components. The next part I will talk about is messaging, this has been a very tricky part of the Entity System.
I have again used CRTP to accomplish this, and I believe allowing a system to register for messages is easier than ever now.
The Messaging system is technically something completely seperate from the Entity System/Component architecture and because of this it is not just Systems that can listen for messages.
Okay so how does it work?
So the Message class is where the CRTP occurs, each derived message type will supply itself as the template parameter for the base class:
class DerivedMessage : public Message
{
public:
DerivedMessage();
virtual ~DerivedMessage(){};
protected:
};
first of all you have to derive the class that will listen to the messages from the MessageListener class supplying the message you will be using:
template < class MessageType >
class MessageListener
{
public:
virtual void HandleMessage(MessageType* message) = 0;
};
class MovementSystem : public System< MovementSystem>,
public MessageListener< MovementMessage>,
public MessageListener< RotationMessage>
{
public:
MovementSystem(MessageManager* msgManager);
virtual void Update();
virtual ~MovementSystem(void);
void HandleMessage(MovementMessage* message);
void HandleMessage(RotationMessage* message);
virtual void RegisterMessages();
};
void MovementSystem::RegisterMessages()
{
mMessageManager->RegisterListener< MovementMessage>(this);
mMessageManager->RegisterListener< RotationMessage>(this);
}
Finally this is a little demo program that shows the use of the ECS and messaging:
int _tmain(int argc, _TCHAR* argv[])
{
MessageManager messManager;
EntityManager manager(& messManager);
Entity* newEnt = manager.CreateEntity( string( "MyFirstEntity" ) );
newEnt->AddComponent< PositionComponent>( newEnt );
newEnt->AddComponent< VelocityComponent>( newEnt );
newEnt->AddSystem< MovementSystem>();
messManager.SendMessage< MovementMessage>( 40.0f, 0.2f, 0.0f );
messManager.SendMessage< RotationdMessage>( 20.0f, 0.0f, 0.0f );
return 0;
}
So I believe this is a fairly flexible approach, there are probably a few more things that I could do to make this better but for now I am going to leave it as it is and try and re-implement all the functionality that is in my previous version of the ECS. Once this is all integrated back into my Engine then I will run some tests and see if there is need for any more changes.
All is going well after a lot of frustrating times with templates. There are still some things that need tidying up to ensure the system is a little more robust but I am very happy with the progress.
Thanks :)