6

我正在尝试创建一个实体/组件系统,该系统会自动匹配合适的实体和合适的系统。我正在使用std::bitsetandRTTI为每个组件类型自动分配一个位值。

系统定义如下:MovementSystem : System<Position, Velocity>.

MovementSystemPosition,在本例中,接受任何同时具有和Velocity组件(以及任何其他组件)的实体。

为了检查一个实体是否合适,我将系统的位集与实体的位集进行比较。

// 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 后发现了它。这是对的吗?可以进一步改进吗?(在我的游戏中实体会被创建和销毁无数次,所以性能非常重要!)


如果需要(不应该),代码就在这里,但几乎不可能阅读。

4

1 回答 1

5

你的支票

(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在于它的所有按位成员 ( &|和循环遍历每个单词。像,或^,之类的提前终止操作不能与它们交织在一起。这是因为不暴露下词存储,因此您无法自己执行迭代.~none()any()==<std::bitset

但是,如果您要编写自己的 bitset 类,则可以编写一个专用includes()算法来循环每个单词,&直到您提前中断

// test whether this includes other
bool YourBitSet::includes(YourBitSet const& other) const {
    for (auto i = 0; i < NumWords; ++i)
        if ((other.word[i] & ~(this->word[i])) != 0)
            return false;
    return true;
}

一个类似的算法缺少std::bitset将是intersects(),有效地测试(a & b) != 0。目前,您必须先进行按位与,然后进行零测试,而在一个循环中这样做会更有效。如果std::bitset得到更新,如果它们包含includes()intersects()原语会很好。

于 2013-10-08T21:22:49.147 回答