在Python / Pyglet中分离轴定理

时间:2013-05-10 05:59:17

标签: python opengl collision-detection pyglet

我正在尝试使用Pyglet在Python中制作一个(类型)的Asteroids克隆。我想我会尝试一点点幻想并实现分离轴定理来做碰撞。我得到了它的工作,但问题是它的速度很慢。我测试了玩家射击的子弹与屏幕上的小行星之间的双重for-loop碰撞,我认为是二次时间,但是当大约有6颗小行星和6颗子弹时,帧速率从大约60到30 fps下降在屏幕上看起来非常慢,即使是非优化的检测碰撞方式。

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

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

这是一个带有Shape类的文件的直接链接,其中发生了所有碰撞逻辑:shape.py。探查器似乎标记为瓶颈的具体方法是__get_transformed_verts。显然你也可以从那里获得整个回购,但只要知道还有很多没有评论的好。

1 个答案:

答案 0 :(得分:3)

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

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

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