Compose entities from game data
Position, velocity, health, transforms, meshes, and ownership are separate components. Each system requests only the values it reads or writes.
Adding or removing a component immediately changes which queries match the entity. The current composition is the entity's game state.
Run the world once per frame
Initialize the world, import the game module, and call
ecs_progress(). Input, simulation, animation, and rendering
stay inside the ECS schedule.
ecs_init();
ECS_MODULE_IMPORT(game, {});
while (ecs_progress()) {}
ecs_fini(); Order systems with phases
Assign each system to a phase such as EcsPreUpdate,
EcsOnUpdate, or EcsOnRender. Callback parameters
state which components and resources the system reads or writes.
ecs::system("Move")
.phase(EcsOnUpdate)
.each([](
ecs::res<const Time> time,
Position &position,
const Velocity &velocity
) {
position.x += velocity.x * time->dt;
}); This movement system reads frame time and velocity, writes position, and runs during the update phase.
Store frame-wide state in resources
A resource stores one typed value for the world. Use resources for frame time, input state, scene settings, and renderer state.
struct Time { float dt; };
ecs::set_resource(Time{ .dt = 1.0f / 60.0f }); Use relations for scene hierarchy
ChildOf builds parent-child trees. IsA creates
instances that inherit shared component values from an abstract entity.
auto ship = ecs::entity::create("ship");
auto turret = ecs::entity::create("turret").child_of(ship);
auto enemy = ecs::entity::create("Enemy");
enemy.set(Health{ 100 }).abstract();
auto boss = ecs::entity::create("Boss").is_a(enemy); Package game features as modules
Observers react to component changes and custom events. A module registers the components, systems, and observers for one game feature, then imports them through one typed entry point.
#include <cstdio>
struct Game {
void import() {
ecs::observe<ecs::OnSet>().each([](const Health &health) {
std::printf("health: %d\n", health.value);
});
}
};
auto game = ecs::import<Game>(); Reflected components can also be serialized to JSON and inspected through the optional REST explorer while the world is running.