降维检测物体碰撞

最近了解了一种用 扫描线算法检测碰撞 的流程

原来不是叫扫描线算法。。。

拿 2D 游戏,游戏中的物体都是 AABB 盒来说(3D 游戏也是可以用这种方式的。2D 游戏分成 x、y 两个维度,3D 分成 x、y、z 三个维度)
  1 首先以 x 轴 方向列一条直线 line,将所有的物体都投影到该直线上,于是每个物体在 line 上都映射成一条线段,有 起点 start、终点 end。
  2 将这些数据存成一个结构体 struct,包含下面字段:
    startPos、endPos、objectId
  3 将所有数据存放到一个数组 xLineList 中,然后根据 startPos 从小到大进行快排
  4 用如下方式遍历数组:
  totalCount = xLineList.length
  for i=0; i<totalCount; ++i
    for j=i; j<totalCount; ++j
      if objectI.endPos <= objectJ.startPos
        //i 和 j 在 x 轴方向上有碰撞
      else
        break;
  用上述方法拿到了 x 轴上所有相交的物体,在记录碰撞对的时候,静态物体之间的碰撞是可以忽略的,只有 dynamic 和 dynamic 或者 dynamic 和 static 之间的碰撞才有记录的必要,能省就省。用类似的方式拿到 y 轴上所有相交的物体。两个方向上同时相交的则表示在 游戏中发生了碰撞。

  算法时间复杂度理论上是 n*n,但是实际上不会有这么高,一般游戏中,物体相对稀疏,所以很容易就会跳出内层循环。

  当物体移动时,为了避免重新做一遍投影操作,可以直接用二分查找在 xLineList 中查找,然后修改 start、end。也可以用额外的一个 map 来维护每个 struct 在数组中的下标。因为列表基本上是有序的,所以再次排序时,时间复杂度很低。

   其他诸如四叉树、八叉树,最大包围盒树,二维空间划分 BSP,格子划分法等,都可以用来做碰撞检测,但是复杂度上并没有特殊的优势,实现起来复杂度倒是高了不少。如果有特殊的需求倒是可以使用。

原文地址:https://www.cnblogs.com/cg-wang/p/6188950.html