From 5665b1de6eac357be4e037f8e0b555f0d03a38a1 Mon Sep 17 00:00:00 2001 From: NukeBird Date: Thu, 13 Feb 2025 22:25:18 +0300 Subject: [PATCH] Store components in vector --- dinkyecs.hpp | 74 +++++++++++++++++++++++++++++++++++++++++++--------- main.cpp | 1 + 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/dinkyecs.hpp b/dinkyecs.hpp index 1a73160..4c7e243 100644 --- a/dinkyecs.hpp +++ b/dinkyecs.hpp @@ -13,7 +13,14 @@ namespace DinkyECS { typedef unsigned long Entity; -using EntityMap = std::unordered_map; +using EntityMap = std::unordered_map; + +template +struct ComponentStorage +{ + std::vector data; + std::queue free_indices; +}; struct Event { @@ -30,6 +37,7 @@ struct World std::unordered_map $components; std::unordered_map $facts; std::unordered_map $events; + std::unordered_map $component_storages; std::vector $constants; Entity entity() { return ++entity_count; } @@ -58,6 +66,35 @@ struct World $constants.push_back(entity); } + template + size_t make_component() + { + auto &storage = component_storage_for(); + size_t index; + + if (!storage.free_indices.empty()) + { + index = storage.free_indices.front(); + storage.free_indices.pop(); + } + else + { + storage.data.emplace_back(); + index = storage.data.size() - 1; + } + + return index; + } + + template + ComponentStorage &component_storage_for() + { + auto type_index = std::type_index(typeid(Comp)); + $component_storages.try_emplace(type_index, ComponentStorage{}); + return std::any_cast &>( + $component_storages.at(type_index)); + } + template EntityMap &entity_map_for() { @@ -74,6 +111,13 @@ struct World void remove(Entity ent) { EntityMap &map = entity_map_for(); + + if (map.contains(ent)) + { + size_t index = map.at(ent); + component_storage_for().free_indices.push(index); + } + map.erase(ent); } @@ -108,16 +152,24 @@ struct World void set(Entity ent, Comp val) { EntityMap &map = entity_map_for(); - map.insert_or_assign(ent, val); + + if (has(ent)) + { + get(ent) = val; + return; + } + + map.insert_or_assign(ent, make_component()); + get(ent) = val; } template Comp &get(Entity ent) { EntityMap &map = entity_map_for(); - // use .at for bounds checking - std::any &res = map.at(ent); - return std::any_cast(res); + auto &storage = component_storage_for(); + auto index = map.at(ent); + return storage.data[index]; } template @@ -131,10 +183,10 @@ struct World void query(std::function cb) { EntityMap &map = entity_map_for(); - for (auto &[entity, any_comp] : map) + + for (auto &[entity, index] : map) { - Comp &res = std::any_cast(any_comp); - cb(entity, res); + cb(entity, get(entity)); } } @@ -144,13 +196,11 @@ struct World EntityMap &map_a = entity_map_for(); EntityMap &map_b = entity_map_for(); - for (auto &[entity, any_a] : map_a) + for (auto &[entity, index_a] : map_a) { if (map_b.contains(entity)) { - CompA &res_a = std::any_cast(any_a); - CompB &res_b = get(entity); - cb(entity, res_a, res_b); + cb(entity, get(entity), get(entity)); } } } diff --git a/main.cpp b/main.cpp index 3353c74..c62f671 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,7 @@ #include "dinkyecs.hpp" #include "point.hpp" #include +#include #define REQUIRE(X) assert(X);