As a pattern ECS and data oriented programming in general are closer to pure C than C++.
Entity component systems consist of three major elements.
- Components are simply holding data; they shouldn't hold any logic. A simple struct should be enough to model them in C.
- Systems is where all your logic lives.
- Finally, Entities don't hold anything (logic or data). They are conceptually just a way of connecting components together. These can be represented as an ID in the component.
As an example you may have a game where your entities can have two components. A position component and a health component.
These can be represented as two structs. Both structs hold an entity_id.
For every different type of component you need a list or an array of that component.
To make things simpler I put everything in a single struct, sort of the root of the ECS.
Also, for simplicity I am using just a member array. You may need to consider a better approach like a binary tree where the key of each node is the id of the component's entity.
Based on these data structres you could define your systems as simple stateless functions. In ECS systems are meant to represent transformations that change the state of a component.
// a simplistic way of creating a new entity
void create_entity(ComponentLists* components)
int id = ENTITIES++;// global number of entities
components.health_components[id].entity_id = id;
components.position_components[id].entity_id = id;
//initialise any other variable here
void update_health_system(Health* h, ComponentLists* components)
if(h->current_health <= 0)
kill_entity(components, h->entity_id);// this will remove all components that refer to that entity_id
void update_position_system(Position* p, ComponentLists* components)
if(p->y <= 0)
// for simplicity's sake we assume that the id is the index.
// In a real world example this won't be enough.
// You may want to use a different data structure instead like a hash map or a binary tree.
Health* h = components.health_components[p->entity_id];
Putting everything together, this is how a main loop could look like.
/*Now you can update each system one by one*/
for(int i = 0; i < components.total_position_components; ++i)
for(int i = 0; i < components.total_health_components; ++i)