#include #include #include #include #include #include #include using namespace fmt; struct Position { double x, y; }; struct Velocity { double x, y; }; typedef unsigned long Entity; typedef std::unordered_map EntityMap; struct World { unsigned long entity_count = 0; std::unordered_map $components; Entity entity() { return ++entity_count; } template EntityMap& entity_map_for() { return $components[std::type_index(typeid(Comp))]; } template void assign(Entity ent, Comp val) { EntityMap &map = entity_map_for(); map[ent] = val; } template Comp &component(Entity ent) { EntityMap &map = entity_map_for(); std::any &res = map[ent]; return std::any_cast(res); } template void system(std::function cb) { EntityMap &map = entity_map_for(); for(auto& [entity, any_comp] : map) { Comp &res = std::any_cast(any_comp); cb(entity, res); } } template void remove(Entity ent) { EntityMap &map = entity_map_for(); map.erase(ent); } template void system(std::function cb) { EntityMap &map_a = entity_map_for(); EntityMap &map_b = entity_map_for(); for(auto& [entity, any_a] : map_a) { if(map_b.contains(entity)) { CompA &res_a = std::any_cast(any_a); CompB &res_b = component(entity); cb(entity, res_a, res_b); } } } }; int main() { World me; Entity test = me.entity(); Entity test2 = me.entity(); me.assign(test, {10,20}); me.assign(test, {1,2}); me.assign(test2, {1,1}); me.assign(test2, {10,20}); Position &pos = me.component(test); println("GOT POS x={}, y={}", pos.x, pos.y); Velocity &vel = me.component(test); println("GOT VELOCITY x={}, y={}", vel.x, vel.y); println("--- Position only system:"); me.system([](const auto &ent, auto &pos) { println("entity={}, pos.x={}, pos.y={}", ent, pos.x, pos.y); }); println("--- Velocity only system:"); me.system([](const auto &, auto &vel) { println("vel.x={}, vel.y={}", vel.x, vel.y); }); println("--- Manually get the velocity in position system:"); me.system([&](const auto &ent, auto &pos) { Velocity &vel = me.component(ent); println("entity={}, vel.x, vel.y, pos.x={}, pos.y={}", ent, vel.x, vel.y, pos.x, pos.y); }); println("--- Query only entities with Position and Velocity:"); me.system([&](const auto &ent, auto &pos, auto &vel) { println("entity={}, vel.x, vel.y, pos.x={}, pos.y={}", ent, vel.x, vel.y, pos.x, pos.y); }); // now remove Velocity me.remove(test); println("--- After remove test, should only result in test2:"); me.system([&](const auto &ent, auto &pos, auto &vel) { println("entity={}, vel.x, vel.y, pos.x={}, pos.y={}", ent, vel.x, vel.y, pos.x, pos.y); }); return 0; }