【问题标题】:Avoid O(n^2) complexity for collision detection避免碰撞检测的 O(n^2) 复杂度
【发布时间】:2011-02-04 09:13:40
【问题描述】:

我正在开发一个简单的基于图块的 2D 游戏。我有一个关卡,里面填充了可以与图块以及彼此交互的对象。检查与 tilemap 的碰撞相当容易,并且可以对具有线性复杂度的所有对象完成。但是现在我必须检测对象之间的碰撞,并且现在我必须检查每个对象与其他所有对象,这会导致平方复杂度。

我想避免平方复杂度。是否有任何众所周知的方法来减少对象之间的碰撞检测调用。是否有任何易于维护并允许一次拒绝许多冲突的数据结构(可能像 BSP 树)。

例如,关卡中的对象总数约为 500 个,一次在屏幕上看到的对象总数约为 50 个...

谢谢!

【问题讨论】:

  • 您想要对所有物体进行碰撞检测还是只对可见物体进行碰撞检测?
  • 嗯。还不确定。我想我可以忽略与屏幕外物体的碰撞
  • 在这种情况下,您只能收集可见对象并对它们进行碰撞检测。仍然是 O(n^2) 时间复杂度。

标签: complexity-theory collision-detection


【解决方案1】:

为什么不让图块存储有关哪些对象占据它们的信息。然后,只要将对象移动到新图块,就可以通过查看该图块是否已包含另一个对象来检测碰撞。

这几乎不需要任何费用。

【讨论】:

  • 这还不错,您也可以在此类地图上运行 A*。但请注意,它可能会导致错误和其他限制,例如如果您想在瓷砖或此类物品上放置多个对象。这也导致了所有对象必须适合一个 tile 的限制,否则处理 2x1 tile obj 将变得复杂。等等。
  • 我对tilemaps不熟悉,但是如果tile可以大于两个对象的交集面积,这不是不准确吗?
  • 听起来不错……反正物体一次可以占用很多块,也可以只占用一块块的一部分(对象,小于块)
  • 顺便说一句,我应该遍历所有图块吗?看看他们是否共享一些对象?物体同时移动,一个物体进入瓷砖,另一个物体离开瓷砖,我该如何处理?
  • @SadSido 只需处理对象的移动即可。当一个对象想要占用一个新的瓦片时,它应该锁定瓦片对象,然后查看它是否已经被另一个对象占用。如果是,碰撞,如果不是,则将自己添加到瓷砖并解锁瓷砖,以便其他物体可以尝试占据它。 (当一个对象离开一个瓦片时,它当然应该将自己从瓦片对象中移除)
【解决方案2】:

您可以使用四叉树来划分空间并减少需要检查碰撞的对象数量。

See this article - Quadtree demonstration.

And perhaps this - Collision Detection in Two Dimensions.

Or this - Quadtree (source included)

乍一看,维护树可能需要大量 CPU 资源,但它也显着减少了检查次数(请参阅第一个链接中的演示)。

【讨论】:

  • 另请注意,实际运行时开销相当小,直到您获得很多很多对象。真正的问题是它增加了很多代码复杂性。如果对象的大小始终接近图块的大小,则 Peladao 的解决方案可能会更适合这种情况。
【解决方案3】:

您的游戏已经有了与游戏玩法相关的瓷砖地图的概念。您可以选择此 tilemap 进行碰撞检测,也可以在您的运动场上覆盖一个辅助网格,专门用于精灵跟踪和碰撞检测。

在您的网格中,每个精灵占据一个或多个图块。精灵知道它占据了哪些图块,而图块知道哪些精灵占据了它。当精灵移动时,您只需要检查精灵占据的图块内的碰撞。这意味着根本不需要碰撞检测,除非精灵足够靠近以占据相同的图块,即使那样,您也只需要检查靠近的精灵之间的碰撞。

如果您的游戏玩法中精灵经常聚集在一起,您可能希望将您的网格实现为四叉树,以允许细分每个图块并防止太多精灵占据同一个网格图块。

此外,根据您的实施,您可能需要使用比确定碰撞时稍大的边界框来确定图块占用率。这样你就可以保证精灵在它们的碰撞边界接触之前会重叠并占据同一个图块。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 2022-01-20
    相关资源
    最近更新 更多