Hello, I have been reading about entity component systems and through that I heard about data oriented design. It all sounds very interesting and sounds like it would be very useful to know. However, I am having some trouble implementing this and understanding certain parts of it. As I understand it:
An entity is comprised of components and can effectively just be an ID
A component is the data of an entity and also implicitly labels the entity as having some behavior
A system provides the logic and methods of the components
Based on here: http://t-machine.org/index.php/2009/10/26/entity-systems-are-the-future-of-mmos-part-5/
and here: http://www.dataorienteddesign.com/dodmain/node5.html
It seems the components should be a table/map of some sort using the entity ID as the index/key, as so:
map<int, PositonComponent> positions;
map<int,VelocityComponent>velocities;
positions[test1] = {0.0f, 5.0f};
positions[test2] = {2.0f, 2.0f};
velocities[test1] = {5.0f, 1.0f};
The two big things I'm having trouble understanding are:
What is a good way to have systems act on data from two different components? For example, if the velocity system is to update the position of an entity by adding the velocity to it.
One way I had thought to do it is to iterate through the map of velocity components and check if the entity id being check also exists in the map of position components. So:
for(map<int,Velocity>::iterator Vel= velocities.begin(); Vel != velocities.end(); Vel ++)
{
int key = xVel->first;
if(positions.count(key) >0 )
{
//update position
}
}
This doesn't seem like it would be very efficient though. Another idea I had heard was to also maintain a list of your entities and use a bitfield to keep track of what components they have. Something like:
enum Components
{
POSITION = 1 <<0,
VELOCITY = 1 <<1,
};
So the above would become:
for(map<int,Velocity>::iterator Vel= velocities.begin(); Vel != velocities.end(); Vel ++)
{
int key = xVel->first;
if((componentList[key] & POSITION) )
{
//update position
}
}
I don't know how much better or worse of a solution this would be though. Any input or further suggestions here would be appreciated.
The other problem I'm having trouble figuring out is how to destroy an entity. If an entity is destroyed/removed from play, what is a good way to let the component maps know so that they don't continue trying to update it? I can't imagine checking every map to see if the entity exists there and then removing it would be a great idea. If I used the bitfield idea from above, I could add another enum to represent having no components, and then when the systems are updating, have them check if the component they are trying to update should be removed. So:
for(map<int,Velocity>::iterator Vel= velocities.begin(); Vel != velocities.end(); Vel ++)
{
int key = xVel->first;
if((componentList[key] & NONE))
{
if((componentList[key] & POSITION))
{
//update position
}
}
else
{
//remove this entity from velocity map
}
}
But again, I don't know if this is the best or even a good way to go about this. Any suggestions here would be very appreciated.
Of course, If I am off or mistaken on any other part of this based on this post please tell me. First time posting here so I apologize if there are any formatting/etiquette mistakes in this post