ECS Usage Guide
An Entity Component System works with 3 types :
- Entities
- Components
- Systems
A Component is a small storage structure.
It should define a single component out of a more complex set, representing an Entity.
As said, an Entity is represented by a set of components, which can be dynamically modified.
And a System is something that you would apply on all entities satisfying certain Components, to allow for modification, rendering, …
For example, if you have a component Position and Velocity, you could have a System to update the Position based on the Velocity, and a lot of very different entities could end up with those components and be moved by the same System.
The goal is to separate every actions, and to maximize performances.
Basic usage
- Define Components Components are simple data structures.
struct Position {
int x;
int y;
};
- Create Systems
Systems are functions that process components.
void logging_system(Registry& r,
containers::indexed_zipper<SparseArray<Position>,
SparseArray<Velocity>> zipper)
{
for (auto&& [i, pos, vel] : zipper)
std::cerr << i << ": Position = { " << pos.value().x << ", "
<< pos.value().y << " }" << std ::endl;
std::cerr << i << ": Velocity = { " << vel->x << ", "
<< vel->y << " }" << std ::endl;
}
- Setup Registry
The registry holds the ECS.
Registry r;
r.register_component<Position>();
r.register_component<Velocity>();
- Create Entities
Entity player = r.spawn_entity();
- Add Components to Entities
r.emplace_component<Position>(player, 2, 23);
r.emplace_component<Velocity>(player, 1, 0);
- Register and Run Systems
r.add_{render/update}_system<Position, Velocity>(logging_system);
r.{render/update}();
- Cleanup
r.kill_entity(player);
Complete Example
See the file ecs/ecs_exemple.cpp
Iterating Over Components
Use zipper to iterate over multiple component arrays:
// With index
for (auto&& [i, pos, vel] : containers::indexed_zipper(positions, velocities)) {
// i is the entity ID
}
Passing more parameters to systems
You can simply add more parameters to systems when registering them.
void system([[maybe_unused]] Registry &r,
[[maybe_unused]] containers::indexed_zipper<SparseArray<Position>> zipper,
int bonus_parameter)
{
std::cout << "Int value=" << bonus_parameter << std::endl;
}
// Inside function to register systems
registry.add_render_system<Position>(12); // 12 will be passed as bonus_parameter