代码之家  ›  专栏  ›  技术社区  ›  Louis Langholtz

如何在PlayRho中为身体设置“用户数据”?

  •  0
  • Louis Langholtz  · 技术社区  · 4 年前

    我如何将“用户数据”(即我的应用程序的任意数据)与 PlayRho 0.10.0物理引擎?

    在the Box2D 2.4.1物理引擎,我可以使用 userData a领域 b2BodyDef 我传递给的实例 b2World::CreateBody 函数,并通过调用返回值 b2Body::GetUserData() 你在PlayRho是怎么做到的?

    1 回复  |  直到 4 年前
        1
  •  0
  •   Louis Langholtz    4 年前

    可能的解决方案:

    在您的应用程序中,您可以使用一个数组,其元素是您的用户数据值,其索引与在中创建实体时返回的基础值相匹配 PlayRho .

    例如,对于任何 void* 兼容的用户数据可能如下:

    int main() {
        struct MyEntity {
            int totalHealth;
            int currentHealth;
            int strength;
            int intellect;
        };
    
        std::vector<void*> myUserData;
    
        auto world = World{};
    
        // If you want to pre-allocate 100 spaces...
        myUserData.resize(100);
    
        const auto body = world.CreateBody();
    
        // If your # bodies is unlimited or you don't want to preallocate space...
        if (body.get() >= myUserData.size()) myUserData.resize(body.get());
    
        // Set your user data...
        myUserData[body.get()] = new MyEntity();
    
        // Gets your user data...
        const auto myEntity = static_cast<MyEntity*>(myUserData[body.get()]);
        
        // Frees your dynamically allocated MyEntity instances.
        // Even with Box2D `userData` you may want to free these.
        for (const auto& element: myUserDAta) {
            delete element;
        }
        return 0;
    }
    

    但如果你想避免处理像内存泄漏这样的头痛问题, myUserData 可以改为 std::vector<MyEntity> myUserData; ,以及 new MyEntity() delete element; 可以避免打电话。

    这样做的一些优点:

    • 提供更大的灵活性。用户数据通常是特定于应用程序的。由于您在使用PlayRho时自己实现了此存储,因此可以更自由地将元素设置为您想要的任何类型,并且不必使物理引擎的所有使用都具有相同的用户数据类型。例如,您的用户数据类型可能是特定于世界的,而在Box2D中,您对其的所有使用 userData 字段将具有相同的类型。
    • 避免浪费内存。并非所有应用程序都需要用户数据,因此那些不需要的应用程序不会浪费这些内存,也不会让你修改库代码来避免这种情况。

    缺点:

    • 这与Box2D不同。
    • 如果你不关心额外的灵活性,这可能需要你付出更多的编码努力(因为额外的灵活性也可能为你节省一些编码工作)。

    背景/说明:

    虽然PlayRho物理引擎最初是Box2D物理引擎的一个分支,但PlayRho已经远离了 引用语义 (指针)和朝向 值语义 (值)。因此,指针被替换,“用户数据”被彻底删除,取而代之的是像这种可能的解决方案这样的替代方案。此外,随着向值语义的转变,创建主体的概念从从从世界中获取指向新主体的指针转变为从世界中基本上获取指向新实体的整数索引。该索引充当世界中新实体的标识符,基本上是一个从0开始从世界递增的计数器,每次创建新实体时都会递增。这意味着您可以使用底层主体ID值作为存储用户数据的元素的索引,从数组中进行O(1)次查找。使用 std::unordered_map<b2Body*, b2BodyUserData> 也将提供O(1)查找,但哈希映射在现代硬件上往往不如数组对缓存友好,因此在Box2D中通过为每个主体的用户数据值留出存储空间来避免这种开销比在PlayRho中更有意义。