Store components in vector
This commit is contained in:
parent
336e5a5733
commit
5665b1de6e
2 changed files with 63 additions and 12 deletions
74
dinkyecs.hpp
74
dinkyecs.hpp
|
@ -13,7 +13,14 @@ namespace DinkyECS
|
||||||
{
|
{
|
||||||
typedef unsigned long Entity;
|
typedef unsigned long Entity;
|
||||||
|
|
||||||
using EntityMap = std::unordered_map<Entity, std::any>;
|
using EntityMap = std::unordered_map<Entity, size_t>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct ComponentStorage
|
||||||
|
{
|
||||||
|
std::vector<T> data;
|
||||||
|
std::queue<size_t> free_indices;
|
||||||
|
};
|
||||||
|
|
||||||
struct Event
|
struct Event
|
||||||
{
|
{
|
||||||
|
@ -30,6 +37,7 @@ struct World
|
||||||
std::unordered_map<std::type_index, EntityMap> $components;
|
std::unordered_map<std::type_index, EntityMap> $components;
|
||||||
std::unordered_map<std::type_index, std::any> $facts;
|
std::unordered_map<std::type_index, std::any> $facts;
|
||||||
std::unordered_map<std::type_index, EventQueue> $events;
|
std::unordered_map<std::type_index, EventQueue> $events;
|
||||||
|
std::unordered_map<std::type_index, std::any> $component_storages;
|
||||||
std::vector<Entity> $constants;
|
std::vector<Entity> $constants;
|
||||||
|
|
||||||
Entity entity() { return ++entity_count; }
|
Entity entity() { return ++entity_count; }
|
||||||
|
@ -58,6 +66,35 @@ struct World
|
||||||
$constants.push_back(entity);
|
$constants.push_back(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Comp>
|
||||||
|
size_t make_component()
|
||||||
|
{
|
||||||
|
auto &storage = component_storage_for<Comp>();
|
||||||
|
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 <typename Comp>
|
||||||
|
ComponentStorage<Comp> &component_storage_for()
|
||||||
|
{
|
||||||
|
auto type_index = std::type_index(typeid(Comp));
|
||||||
|
$component_storages.try_emplace(type_index, ComponentStorage<Comp>{});
|
||||||
|
return std::any_cast<ComponentStorage<Comp> &>(
|
||||||
|
$component_storages.at(type_index));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Comp>
|
template <typename Comp>
|
||||||
EntityMap &entity_map_for()
|
EntityMap &entity_map_for()
|
||||||
{
|
{
|
||||||
|
@ -74,6 +111,13 @@ struct World
|
||||||
void remove(Entity ent)
|
void remove(Entity ent)
|
||||||
{
|
{
|
||||||
EntityMap &map = entity_map_for<Comp>();
|
EntityMap &map = entity_map_for<Comp>();
|
||||||
|
|
||||||
|
if (map.contains(ent))
|
||||||
|
{
|
||||||
|
size_t index = map.at(ent);
|
||||||
|
component_storage_for<Comp>().free_indices.push(index);
|
||||||
|
}
|
||||||
|
|
||||||
map.erase(ent);
|
map.erase(ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,16 +152,24 @@ struct World
|
||||||
void set(Entity ent, Comp val)
|
void set(Entity ent, Comp val)
|
||||||
{
|
{
|
||||||
EntityMap &map = entity_map_for<Comp>();
|
EntityMap &map = entity_map_for<Comp>();
|
||||||
map.insert_or_assign(ent, val);
|
|
||||||
|
if (has<Comp>(ent))
|
||||||
|
{
|
||||||
|
get<Comp>(ent) = val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
map.insert_or_assign(ent, make_component<Comp>());
|
||||||
|
get<Comp>(ent) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Comp>
|
template <typename Comp>
|
||||||
Comp &get(Entity ent)
|
Comp &get(Entity ent)
|
||||||
{
|
{
|
||||||
EntityMap &map = entity_map_for<Comp>();
|
EntityMap &map = entity_map_for<Comp>();
|
||||||
// use .at for bounds checking
|
auto &storage = component_storage_for<Comp>();
|
||||||
std::any &res = map.at(ent);
|
auto index = map.at(ent);
|
||||||
return std::any_cast<Comp &>(res);
|
return storage.data[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Comp>
|
template <typename Comp>
|
||||||
|
@ -131,10 +183,10 @@ struct World
|
||||||
void query(std::function<void(const Entity &, Comp &)> cb)
|
void query(std::function<void(const Entity &, Comp &)> cb)
|
||||||
{
|
{
|
||||||
EntityMap &map = entity_map_for<Comp>();
|
EntityMap &map = entity_map_for<Comp>();
|
||||||
for (auto &[entity, any_comp] : map)
|
|
||||||
|
for (auto &[entity, index] : map)
|
||||||
{
|
{
|
||||||
Comp &res = std::any_cast<Comp &>(any_comp);
|
cb(entity, get<Comp>(entity));
|
||||||
cb(entity, res);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,13 +196,11 @@ struct World
|
||||||
EntityMap &map_a = entity_map_for<CompA>();
|
EntityMap &map_a = entity_map_for<CompA>();
|
||||||
EntityMap &map_b = entity_map_for<CompB>();
|
EntityMap &map_b = entity_map_for<CompB>();
|
||||||
|
|
||||||
for (auto &[entity, any_a] : map_a)
|
for (auto &[entity, index_a] : map_a)
|
||||||
{
|
{
|
||||||
if (map_b.contains(entity))
|
if (map_b.contains(entity))
|
||||||
{
|
{
|
||||||
CompA &res_a = std::any_cast<CompA &>(any_a);
|
cb(entity, get<CompA>(entity), get<CompB>(entity));
|
||||||
CompB &res_b = get<CompB>(entity);
|
|
||||||
cb(entity, res_a, res_b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
main.cpp
1
main.cpp
|
@ -1,6 +1,7 @@
|
||||||
#include "dinkyecs.hpp"
|
#include "dinkyecs.hpp"
|
||||||
#include "point.hpp"
|
#include "point.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <fmt/base.h>
|
||||||
|
|
||||||
#define REQUIRE(X) assert(X);
|
#define REQUIRE(X) assert(X);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue