2

我正在尝试使用 Pyglet 在 Python 中制作(某种)小行星克隆。我想我会尝试变得有点花哨并实现分离轴定理来进行碰撞。我让它工作,但问题是它非常缓慢。我在双循环中测试玩家射击的子弹和屏幕上的小行星之间的碰撞,我认为这是二次时间,但是当大约有 6 颗小行星和 6 颗子弹时,帧速率从大约 60 fps 下降到 30 fps在屏幕上,这似乎非常慢,即使对于检测碰撞的非优化方式也是如此。

所以我运行了一个分析器来确定程序在代码中的确切位置挂起。它似乎挂在我将形状顶点转换到世界空间的方法中(我定义了原点周围的形状并使用OpenGL代码转换到世界空间进行绘图,我相信这是正确的方法)。我从 OpenGL 中获取变换矩阵,将其转换为 NumPy 数组,然后将每个顶点乘以该矩阵,得到变换后的顶点。值得注意的是,我在每次碰撞检查时都这样做:我曾经使用 XNA,当我在其中实现 SAT 时(我也在那里制作了一个小行星克隆),顶点也在原点周围定义,然后你必须转换他们使用世界矩阵。

最好将顶点存储在 (0, 0) 周围并转换每个调用,还是只存储转换后的顶点?我觉得算法不应该这么慢,所以我敢打赌我搞砸了一些东西。如果我更擅长分析(我对它很不熟悉),我可能能够获得更完整的图片,但我希望你们可能有一些想法。

这是指向其中包含 Shape 类的文件的直接链接,所有碰撞逻辑都发生在该文件中:shape.py。探查器似乎标记为瓶颈的具体方法是 __get_transformed_verts。显然,您也可以从那里访问整个 repo,但请注意,仍有很多未评论的内容。

4

1 回答 1

3

正如 Nico 在评论中建议的那样,获得良好加速的一种快速方法是首先检查更简单的几何图形。对于 Asteroids 克隆,我猜一个圆圈会很合适(或 3D 球体)。如果圆圈(至少大到足以覆盖您的实际形状)不重叠,则无需进行更昂贵的几何测试。

如果您有很多对象,您可能希望避免每帧进行 n*n 测试。看看空间划分结构/算法。具有大量 2D 移动对象的最简单方案是网格。然后,您只需要测试属于相同或相邻网格单元的对象是否发生碰撞。

我注意到的另一件事:每次测试碰撞时都会生成转换后的顶点。对于未通过圆环测试的每个对象,每个时间步(帧)只生成一次它们会更快。

于 2013-05-10T11:26:36.220 回答