我试图创建一个实体/组件系统,自动匹配合适的实体适合的系统。我使用std::bitset
和RTTI
自动为每个组件类型分配一个位值。
系统定义如下:MovementSystem : System<Position, Velocity>
。
MovementSystem
接受同时包含Position
和Velocity
组件(以及任何其他组件)的任何实体。
为了检查实体是否合适,我将系统的bitset与实体的bitset进行比较。
// Let's assume there are max 4 components
1 1 0 1 // Entity bitset
^ ^ ^
Position Velocity OtherB
1 1 0 0 // Suitable example system bitset
^ ^
Position Velocity
1 1 1 0 // Unsuitable example system bitset
^ ^ ^ // Entity does not have OtherA!
Position Velocity OtherA
到目前为止,我的解决方案就是这个:
if(entityBitset & systemBitset) == systemBitset)) { /* entity is suitable! */ }
似乎可以工作,但是我在白板上涂抹了bitset后发现了它。这是对的吗?可以进一步改进吗? (实体将在我的游戏中创建和销毁很多次,因此性能非常重要!)
如果需要,代码为here(不应该),但几乎不可能阅读。
答案 0 :(得分:3)
您的支票
a & b == b; // check whether b is a subset of a
检查b
是a
的子集,还是等效的,a
是否包含/ b
。请注意,您要创建一个临时,然后是break-early operator==
。
这相当于检查b
和a
的差异是否为空(请注意顺序!)
(b & ~a).none();
这同样会很快:一个临时的,然后是休息时间.none()
鉴于std::bitset
的界面,这是你能得到的速度。 std::bitset
的问题在于,所有按位成员(&
,|
,^
和~
都会循环遍历每个单词。提前终止操作,例如{{} 1}},none()
,any()
或==
不能与它们交织在一起。这是因为<
没有公开底层字存储,因此您无法自己执行迭代
但是,如果您要编写自己的bitset类,则可以编写一个专用的std::bitset
算法,循环遍历每个单词,执行includes()
直到您提前中断
&
// test whether this includes other
bool YourBitSet::includes(YourBitSet const& other) const {
for (auto i = 0; i < NumWords; ++i)
if (otherword[i] & ~(this->word[i]) != 0)
return false;
return true;
}
中遗漏的类似算法为std::bitset
,以便有效地测试intersects()
。目前你必须首先按位进行,然后进行零测试,而这样可以在一个循环中更有效地完成。如果a & b != 0
得到更新,那么如果它们包含std::bitset
和includes()
原语就会很好。