diff options
-rw-r--r-- | entity.hpp | 8 | ||||
-rw-r--r-- | world.cpp | 62 | ||||
-rw-r--r-- | world.hpp | 17 |
3 files changed, 66 insertions, 21 deletions
diff --git a/entity.hpp b/entity.hpp new file mode 100644 index 0000000..34cc84d --- /dev/null +++ b/entity.hpp @@ -0,0 +1,8 @@ +#ifndef entity_hpp +#define entity_hpp + +#include <stdint.h> + +using Entity_Id = uint32_t; + +#endif @@ -32,17 +32,6 @@ void* Slinky::get(Entity_Id eid, int mapping, int size) { return e; } -void Slinky::remove(Entity_Id eid, int mapping, int size) { - int end = (--count) * size; - assert(eid == entities[mapping]); - (void)eid; - memmove( - (char*)data + mapping * size, - (char*)data + end * size, - size - ); -} - void Pool::init(Arena* a, Component_Mask m) { int i, coff; mask = m; @@ -59,9 +48,11 @@ void Pool::init(Arena* a, Component_Mask m) { } Slinky& Pool::get_slinky(Arena* a) { - int idx = slinky_count - 1; - if (slinkies[idx].count < slinky_size) { - return slinkies[idx]; + int i, e = slinky_count; + for (i = 0; i < e; i++) { + Slinky& s = slinkies[i]; + if (s.count < slinky_size) + return s; } assert(slinky_count < max_slinkies); Slinky& s = slinkies[slinky_count++]; @@ -78,9 +69,34 @@ void* Pool::add(Arena* a, Entity_Id eid) { } void Pool::remove(Entity_Id eid) { - Mapping m = mapping[entity_index(eid)]; + Mapping& m = mapping[entity_index(eid)]; Slinky& s = slinkies[m.slinky]; - s.remove(eid, m.mapping, size); + assert(m.slinky >= 0); + if (count > 1) { + int idx = slinky_count - 1; + Entity_Id le; + void* last; +#ifdef DEBUG + last = 0; +#endif + for (; idx >= 0; idx--) { + Slinky& s = slinkies[idx]; + int& c = s.count; + if (c) { + c--; + last = (char*)s.data + c * size; + le = s.entities[c]; + s.entities[c] = 0; + break; + } + } + assert(last != 0); + memcpy((char*)s.data + m.mapping * size, last, size); + s.entities[m.mapping] = le; + mapping[entity_index(le)] = m; + m = Mapping { -1, -1 }; + } else + s.count--; count--; } @@ -122,6 +138,7 @@ void World::init(Arena* a) { arena = a; count = 0; free_count = 0; + dq_count = 0; for (i = 0; i < max_entities; i++) versions[i] = 1; for (i = 0; i < max_pools; i++) @@ -232,3 +249,16 @@ void World::destroy(Entity_Id e) { versions[entity_index(e)]++; } +void World::qdestroy(Entity_Id e) { + assert(e); + assert(dq_count < max_entities); + dq[dq_count++] = e; +} + +void World::update() { + int i, e = dq_count; + Entity_Id* d = dq; + for (i = 0; i < e; i++, d++) + destroy(*d); + dq_count = 0; +} @@ -3,16 +3,20 @@ struct Arena; +#include "entity.hpp" + #include <stdint.h> #include <new> +#include <tuple> #include <utility> - +extern "C" { +#include "plat.h" +} using Component_Mask = uint64_t; -using Entity_Id = uint32_t; #define max_entities 1024 -#define slinky_size 128 +#define slinky_size 1 #define max_components 64 #define max_slinkies (max_entities / slinky_size) @@ -36,7 +40,6 @@ struct Slinky { void init(Arena* a, int size); void* add(Entity_Id eid, int size, int& mapping); void* get(Entity_Id eid, int mapping, int size); - void remove(Entity_Id eid, int mapping, int size); }; struct Pool { @@ -71,8 +74,9 @@ struct World { uint8_t versions[max_entities]; Entity_Id entities[max_entities]; Entity_Id freelist[max_entities]; + Entity_Id dq[max_entities]; Arena* arena; - int count, free_count; + int count, dq_count, free_count; void init(Arena* a); uint64_t hash_mask(Component_Mask m); @@ -122,6 +126,8 @@ struct World { void* get(Entity_Id eid, int cid); void remove(Entity_Id eid, int cid); void destroy(Entity_Id e); + void qdestroy(Entity_Id e); + void update(); struct View { World* w; @@ -172,6 +178,7 @@ struct World { Slinky& s = p->slinkies[ptr >> slinky_size_bit]; int si = &s - p->slinkies; int off = ptr - (si << slinky_size_bit); + assert(s.entities[off]); return s.entities[off]; } }; |