比简单地检查每对物体更好地进行2D碰撞检测

时间:2011-05-08 12:34:22

标签: java 2d collision-detection

我需要我的2D碰撞检测算法可扩展,但我担心它不是。我的算法做到了这一点:

  1. 创建精灵对象的LinkedList(包括所有数据)

    private LinkedList<Sprite> collisionSpritesList = new LinkedList<Sprite>();

  2. 主游戏循环然后将所有精灵添加到LinkedList:

    public void GameUpdate() { collisionSpritesList.add(avatar); collisionSpritesList.add(enemy1); collisionSpritesList.add(enemy2); }

  3. 然后调用collisionCheck()方法;它循环遍历列表中所有实体对寻找碰撞。然后完全删除LinkedList。这是因为实体需要使用新位置进行更新。

  4. public boolean checkCollision() {

    for(int i = 0; i < collisionSpritesList.size(); i++)
    {
    
    
    for(int j = 0; j < collisionSpritesList.size(); j++)
     {
    if(i != j)
     {
         if(collisionSpritesList.get(i).getRectangle().intersects(collisionSpritesList.get(j).getRectangle()))
         {
            Point p = gridMap.getRandomWalkableLocation();
            collisionSpritesList.get(j).setLocation(p.x * gridMap.getCellSize(), p.y * gridMap.getCellSize());
            collisionSpritesList.clear();
            return true;
         }
      }
    

    } }

      collisionSpritesList.clear();
        return false;
    }
    

    我的问题是这种检查碰撞的方式效率如何?它应该以不同的方式完成吗?如果是这样,哪些方法可以扩展?

3 个答案:

答案 0 :(得分:1)

我会考虑使用QuadTree来细分您的空间,然后只检查位于相同“桶”或空间中的精灵中的碰撞。

答案 1 :(得分:0)

如果您可以在考虑其位置的数据结构中对精灵进行分区,那么您可以限制需要执行的碰撞​​测试次数。

使用的一种数据结构称为四叉树。以下limk描述了如何结合四叉树使用碰撞检测:

http://lab.polygonal.de/2007/09/09/quadtree-demonstration/

答案 2 :(得分:0)

保留一个排序列表(按其中一个轴排序)并在每个循环中使用气泡排序进行计算,这将缩放为O(n * x),x为每个循环的平均移动量。

然后使用扫描算法,其中O(n * k)为k,排序轴上的平均重叠

(列表按照minX排序)

for(int i = 0; i < collisionSpritesList.size(); i++)
{
  for(int j = i+1; j < collisionSpritesList.size(); j++)
   {
     if(collisionSpritesList.get(j).getRectangle().minX()>collisionSpritesList.get(i).getRectangle().maxX())
         break;//breakout inner for when no overlap on x-axis possible

     if(collisionSpritesList.get(i).getRectangle().intersects(collisionSpritesList.get(j).getRectangle()))
      {
        Point p = gridMap.getRandomWalkableLocation();
        collisionSpritesList.get(j).setLocation(p.x * gridMap.getCellSize(), p.y * gridMap.getCellSize());
        return true;
      }
  }
}