简单的效率问题C++ (内存分配)..也许一些碰撞检测有帮助?

发布于 2024-07-10 04:02:25 字数 817 浏览 10 评论 0原文

我正在用 C++ 编写一个类似街机的小游戏(多向 2d 空间射击游戏),并且正在完成碰撞检测部分。

以下是我的组织方式(我只是编造出来的,所以它可能是一个糟糕的系统):

每艘船都由圆形组件组成 - 每艘船中的组件数量是任意的(更多组件,更多 CPU 周期)。 我有一个 maxComponent 距离,是在创建船舶时计算的,这基本上是我可以从船舶中心到最远组件边缘绘制的最长线。 我跟踪屏幕上的内容,并使用 maxComponentDistance 来查看它们是否足够接近以发生碰撞。

如果它们非常接近,我就会开始检查不同船舶的组件是否相交。 这就是我的效率问题出现的地方。

我有组件相对于船舶中心的 (x,y) 位置,但它没有考虑船舶当前如何旋转。 我保持它们是相对的,因为我不想每次船舶移动时都重新计算组件。 因此,我有一个用于旋转计算的小公式,并返回一个对应于相对于船舶中心的旋转考虑位置的二维向量。

碰撞检测位于 GameEngine 中,并且使用 2d 向量。 我的问题是关于返回类型。 我是否应该在每次调用该函数时创建并返回一个 2d 向量对象 或者 我应该给该组件对象一个额外的私有二维向量变量,在调用函数时编辑私有变量,并返回指向该对象的指针吗?

我不确定内存分配的效率与拥有永久、可编辑、私有变量的效率。 我知道还必须为私有变量分配内存,但不是每次检查冲突时都分配内存,只有在创建新组件时才分配内存。 在我的环境中,组件并不是恒定的,因为它们会在飞船被摧毁时被删除。

这是我的主要困境。 我也非常感谢任何有关我的实际碰撞检测系统设计的指示。 这是我第一次对此进行破解(也许应该阅读一下)

提前致谢。

I'm writing a little arcade-like game in C++ (a multidirectional 2d space shooter) and I'm finishing up the collision detection part.

Here's how I organized it (I just made it up so it might be a shitty system):

Every ship is composed of circular components - the amount of components in each ship is sort of arbitrary (more components, more CPU cycles). I have a maxComponent distance which I calculate upon creation of the ship which is basically the longest line I can draw from the center of the ship to the edge of the furthest component. I keep track of stuff onscreen and use this maxComponentDistance to see if they're even close enough to be colliding.

If they are in close proximity I start checking to see if the components of different ships intersect. Here is where my efficiency question comes in.

I have a (x,y) locations of the component relative to the ship's center, but it doesn't account for how the ship is currently rotated. I keep them relative because I don't want to have to recalculate components every single time the ship moves. So I have a little formula for the rotation calculation and I return a 2d-vector corresponding to rotation-considerate position relative to the ships center.

The collision detection is in the GameEngine and it uses the 2d-vector. My question is about the return types. Should I just create and return a 2d-vector object everytime that function is called
or
should I give that component object an additional private 2d-vector variable, edit the private variable when the function is called, and return a pointer to that object?

I'm not sure about the efficiency of memory allocation vs having a permanent, editable, private variable. I know that memory would also have to be allocated for the private variable, but not every time it was checked for collisions, only when a new component was created. Components are not constant in my environment as they are deleted when the ship is destroyed.

That's my main dilemma. I would also appreciate any pointers with the design of my actual collision detection system. It's my first time giving a hack at it (maybe should have read up a bit)

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

她说她爱他 2024-07-17 04:02:25

您绝对应该尽量避免在每次调用 getter 函数时为组件向量分配内存。 相反,尽可能少地进行分配。 例如,您可以在船舶的组件组成发生变化时执行此操作,甚至很少发生(通过过度分配)。

当然,您也可以研究内存池,在内存池中预先分配大量此类组件并将其放入池中,以便您可以在恒定时间内分配新组件。

作为进行这种碰撞检测时的一般要点(如果太明显的话,我们深表歉意):计算距离的平方,而不是计算平方根。 :)

You should absolutely try to avoid doing memory allocations for your component-vector on each call to the getter-function. Do the allocation as seldom as possible, instead. For instance, you could do it when the component composition of the ship changes, or even more seldom (by over-allocating).

You could of course also investigate memory pools, where you pre-allocate lots of such components and put in a pool, so you can allocate a new component in constant time.

As a general (and apologies if it's too obvious) point when doing this kind of collision-detection: square the distances, rather than computing the square roots. :)

§对你不离不弃 2024-07-17 04:02:25

如果你的 2D 向量只是:

 class Vector2D { double x, y; };

那么一定要返回它! 例如:

  Vector2D function( ... );

或者通过引用传递:

  void function( Vector2D * theReturnedVector2D, ... );

不惜一切代价避免:

 vector<double> function(...);

Vector 类固有的常量堆分配/释放是一个错误!


从计算角度来说,复制您自己的 Vector2D 类非常便宜。 与 Vector<> 不同,您自己的 Vector2D 类可以合并您喜欢的任何方法。

我过去曾使用此功能来合并distanceToOtherPointSquared()、scanfFromCommandLineArguments()、printfNicelyFormatted() 和operator[](int) 等方法。


或者我应该给该组件对象一个额外的私有二维向量变量,在调用函数时编辑私有变量,并返回指向该对象的指针?

多个函数调用使先前的数据无效。 这是灾难的根源!

If your 2D vector is just:

 class Vector2D { double x, y; };

Then by all means return it! E.g:

  Vector2D function( ... );

Or pass by reference:

  void function( Vector2D * theReturnedVector2D, ... );

Avoid at all costs:

 vector<double> function(...);

The constant heap allocation/deallocation inherent to the Vector class is a mistake!


Copying your own Vector2D class is very cheap, computationally speaking. Unlike Vector<>, your own Vector2D class can incorporate whatever methods you like.

I've used this feature in the past to incorporate methods such as distanceToOtherPointSquared(), scanfFromCommandLineArguments(), printfNicelyFormatted(), and operator[](int).


or should I give that component object an additional private 2d-vector variable, edit the private variable when the function is called, and return a pointer to that object?

Watch out for multiple function calls invalidating previous data. That's a recipe for disaster!

对岸观火 2024-07-17 04:02:25
  1. 您可以从返回一个向量开始,然后对其进行基准测试。 谁知道呢,它可能足够快。 使用分析器,您甚至可以查看哪些部分占用了运行时间。
  2. 您可以使用内存池来重用向量并减少复制
  3. 您可以尝试坐标的享元模式,以减少复制和分配(如果它们在整个引擎中重复)。
  4. 将数据保留在组件中是减少分配的好方法,但会在设计中引入一些陷阱,例如谁使用向量取决于组件的生命周期。 内存池可能更好。
  1. You can start by just returning a vector, and benchmark it. Who knows, it could be fast enough. With a profiler you can even see what part takes the run time.
  2. You can use a Memory Pool to reuse vectors and reduce copying
  3. You can try the Flyweight pattern for the coordinates to reduce copying and allocating, if they repeat throughout the engine.
  4. Keeping the data in the component is a good way to reduce allocations, but introduces some gotchas into your design, like that whoever uses the vector depends on the lifecycle of the component. A memory pool is probably better.
清醇 2024-07-17 04:02:25

不要使用 2D 矢量。 相反,使用向量。 对于碰撞检测也是如此。 这里使用二维向量是错误的数据结构。

根据函数的内容,编译器将能够执行 NRVO(即 命名返回值优化)这意味着在最佳情况下,返回向量没有开销,即它永远不会被复制。 但是,只有当您使用函数的返回值来初始化新实例,并且编译器能够跟踪函数内部的执行路径并查看每个返回路径返回相同的对象时,才会发生这种情况。 请考虑以下两点:

vector<int> f(int baz) {
    vector<int> ret;
    if (baz == 42)
        ret.push_back(42);
    return ret;
}

vector<int> g(int baz) {
    if (baz == 42)
        return vector<int>(1, 42);
    else
        return vector<int>();
}

编译器可以对 f 的调用执行 NRVO,但不能对 g 的调用执行 NRVO。

Do not use a 2D vector. Rather, use a vector of points. Likewise for your collision detection. Using a 2D vector here is just the wrong data structure.

Depending on the content of the function, the compiler will be able to perform NRVO (that is, named return value optimization) which means that in the optimal case, returning a vector has no overhead, i.e. it's never copied. However, this only happens when you use the return value of your function to initialize a new instance, and when the compiler is able to trace the execution paths inside the function and see that for each return path, the same object is returned. Consider the following two:

vector<int> f(int baz) {
    vector<int> ret;
    if (baz == 42)
        ret.push_back(42);
    return ret;
}

vector<int> g(int baz) {
    if (baz == 42)
        return vector<int>(1, 42);
    else
        return vector<int>();
}

The compiler can perform NRVO for calls to f, but not for g.

白昼 2024-07-17 04:02:25

在堆上分配内存和在堆栈上分配内存有很大区别。 在堆上分配,例如使用 new/delete 或 malloc/free 非常慢。 在堆栈上分配确实非常快。 对于堆栈,通常最慢的部分是复制对象。 因此,请注意向量等,但返回简单的结构可能是可以的。

There's a big difference between allocating memory on the heap and on the stack. Allocating on the heap, e.g., using new/delete or malloc/free is very slow. Allocating on the stack is really quite fast. With the stack, usually the slow part is copying your object. So watch out for vector and such, but returning simple structures is probably OK.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文