I'm trying to code my own Entity Component System, and I want a fast (constant time where possible) but also memory efficient way of accessing a component of an entity.
A global map is used ( std::unordered_map
) that maps each entity to a sorted vector which contains their components:
Key Value
--- -----
EntityA -> Sorted vector of components
EntityB -> Sorted vector of components
[..] -> [..]
Each entity has a bitset that indicates what components the entity has ie. :
|C0 |C1 |C2 |C3 |C4 |C5
0 0 1 0 1 1
and on the map:
Key Value
--- -----
EntityA -> [C2,C4,C5]
As components get added rarely I can afford the cost of a sorted insertion, but I definitely want fast access.
Now I know from the bitset that C4 is the second element set(counting from the left) so it should be at the second vector index.
How can I write that into a method that will return the component of an entity given the ID of that component type? eg.
Component* getComponent(ComponentID id){ // component id of C5 should be 6 since it occupies the 6th position of the bitset
return [..];
}
Suppose our members are:
std::bitset<6> bits;
std::vector<Component> comps;
Then:
Component* getComponent(int id) {
// we need to find how many bits are set for ids < id
// first, make sure this one is set:
if (!bits[id]) return nullptr;
// then, let's count
int idx = 0;
for (int i = 0; i < id; ++i) {
if (bits[i]) ++idx;
}
// now, just return the right pointer
return &comps[idx];
}
You could also use std::bitset::test
instead of the index operator if you want to do bounds checking.
A quicker solution might be something like this:
Component* getComponent(int id) {
if (!bits[id]) return nullptr;
// flip id and get a mask
// if we have C0 .. C5, and we pass in 4
// we want the mask 0x111100
unsigned long mask = (1 << (bits.size() - id)) - 1;
mask = ~mask;
// apply the mask to the bitset
// so from 0x001011, we get 0x001000
unsigned long new_bits = bits.to_ulong() & mask;
// count how many bits are set there
unsigned int popcnt = __builtin_popcount(new_bits);
// and there we have it
return &comps[popcnt];
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.