如何在 PlayRho 中为 body 设置 "user data"?
How to set "user data" for a body in PlayRho?
如何将“用户数据”(即我的应用程序的任意数据)与 PlayRho 0.10.0 物理引擎中的主体相关联?
在 Box2D 2.4.1 物理引擎中,我可以使用传递给 b2BodyDef
实例的 userData
字段将“用户数据”与主体相关联=14=] 函数并通过调用 b2Body::GetUserData()
取回值。您如何在 PlayRho 中执行此操作?
可能的解决方案:
在您的应用程序中,您可以使用一个数组,其元素是您的 user-data 值,其索引与在 PlayRho.
中创建主体返回的基础值相匹配
例如,任何 void*
兼容用户数据的 simple/naive 实现可能如下:
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 中的不同。
- 如果您不关心是否具有额外的灵活性,这可能需要您付出更多的编码工作(因为额外的灵活性也可能会为您节省一些编码工作)。
Background/explanation:
虽然 PlayRho 物理引擎最初是作为 Box2D 物理引擎的一个分支,但 PlayRho 已经从 引用语义 (指针)转向 值语义(值)。因此,指针被替换,“用户数据”被彻底删除,以支持像这种可能的解决方案这样的替代方案。此外,随着向值语义的转变,创建 body 的概念从获取指向新 body 的指针转变为基本上获取指向新 body 的整数索引】 而是从世界回来。该索引充当世界中新 body 的标识符,基本上是从 0 开始的世界递增计数器,每次创建新 body 时递增。这意味着您可以使用基础 body ID 值作为存储用户数据的元素的索引从数组进行 O(1) 查找。使用 std::unordered_map<b2Body*, b2BodyUserData>
也将提供 O(1) 查找,但散列映射在现代硬件上往往不如数组缓存友好,因此通过为每个 body 比在 PlayRho 中做的要多。
如何将“用户数据”(即我的应用程序的任意数据)与 PlayRho 0.10.0 物理引擎中的主体相关联?
在 Box2D 2.4.1 物理引擎中,我可以使用传递给 b2BodyDef
实例的 userData
字段将“用户数据”与主体相关联=14=] 函数并通过调用 b2Body::GetUserData()
取回值。您如何在 PlayRho 中执行此操作?
可能的解决方案:
在您的应用程序中,您可以使用一个数组,其元素是您的 user-data 值,其索引与在 PlayRho.
中创建主体返回的基础值相匹配例如,任何 void*
兼容用户数据的 simple/naive 实现可能如下:
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 中的不同。
- 如果您不关心是否具有额外的灵活性,这可能需要您付出更多的编码工作(因为额外的灵活性也可能会为您节省一些编码工作)。
Background/explanation:
虽然 PlayRho 物理引擎最初是作为 Box2D 物理引擎的一个分支,但 PlayRho 已经从 引用语义 (指针)转向 值语义(值)。因此,指针被替换,“用户数据”被彻底删除,以支持像这种可能的解决方案这样的替代方案。此外,随着向值语义的转变,创建 body 的概念从获取指向新 body 的指针转变为基本上获取指向新 body 的整数索引】 而是从世界回来。该索引充当世界中新 body 的标识符,基本上是从 0 开始的世界递增计数器,每次创建新 body 时递增。这意味着您可以使用基础 body ID 值作为存储用户数据的元素的索引从数组进行 O(1) 查找。使用 std::unordered_map<b2Body*, b2BodyUserData>
也将提供 O(1) 查找,但散列映射在现代硬件上往往不如数组缓存友好,因此通过为每个 body 比在 PlayRho 中做的要多。