我的碰撞检测在java applet中生成低fps

时间:2012-01-31 12:10:50

标签: java applet collision-detection

这是我第一次尝试碰撞算法。我尝试用边界检查对象的rect大小。现在,在这个应用程序中,我制作了运行项目符号并检查是否在没有时间延迟的情况下发生了冲突。问题是,当我产生大约30-40个子弹时,fps变得如此之低。如果有人可以教我一种写入碰撞检测的强大方法,我会很高兴。

顺便说一下,我使用了一个java Vector集合(也许迭代速度不够快?或者我的代码太乱了)

public void checkBoundary(int width, int height) //width and height of the applet
{
    for(int i = 0; i < vec.size(); i++)
    {
        if(vec.get(i).x + vec.get(i).width <= 0 ||
            vec.get(i).y + vec.get(i).height <= 0 ||
            vec.get(i).x >= width ||
            vec.get(i).y >= height)
            vec.remove(i);
    }
}

此Vector存储子弹的对象,其中(x,y)为左下角,(宽度,高度)。

2 个答案:

答案 0 :(得分:2)

首先,您的算法不正确,因为当您使用vec.remove(i);删除时,i+1元素将成为i元素,因此您跳过了一个元素。

性能问题来自以下事实:在最坏的情况下,每个移除成本O(n),因为每个后续元素都需要向左移动。试试这个:

public void checkBoundary(int width, int height) //width and height of the applet
{
  LinkedList<T> outofbounds = new LinkedList<T>();
  for(int i = 0; i < vec.size(); i++)
  {
    if(vec.get(i).x + vec.get(i).width <= 0 ||
        vec.get(i).y + vec.get(i).height <= 0 ||
        vec.get(i).x >= width ||
        vec.get(i).y >= height)
        outofbounds.add(vec.at(i)); 
  }
  vec.removeAll(outofbounds);

}

编辑:

正如 Frozen Spider 指出的那样,removeAll很贵。它的复杂度为O(outofbounds.size()*vec.size()),即O(n^2)。稍微改变逻辑时,您可以推导出一种保证在O(vec.size())中起作用的算法。

public void checkBoundary(int width, int height) //width and height of the applet
{
  LinkedList<T> newvec = new LinkedList<T>(); 
  for(int i = 0; i < vec.size(); i++)
  {
    if(vec.get(i).x + vec.get(i).width <= 0 ||
        vec.get(i).y + vec.get(i).height <= 0 ||
        vec.get(i).x >= width ||
        vec.get(i).y >= height)
        continue;

        newvec.add(vec.at(i)); 
  }
  vec.clear();
  // or vec = newvec if there are no others reference sharing the same object as vec
  vec.addAll(newvec); 

}

答案 1 :(得分:1)

remove()是一项非常昂贵的操作,创建新列表,将所需元素复制到其中并用新的列表替换原始列表要快得多。

我还建议您使用ArrayList代替Vector。如果您需要同步,请在ArrayList中打包Collections.synchronizedList()

试试这个,几乎立即起作用 - &lt; 16毫秒(0.016秒)超过100k元素:

public static void checkBoundary(int width, int height) // width and height of the applet
{
    int size = vec.size();
    List <YourObjectType> newVec = new ArrayList <YourObjectType>(size);
    for (int i = 0; i < size; i++) {
        YourObjectType element = vec.get(i);
        if (element.x + element.width > 0 && 
            element.y + element.height > 0 &&
            element.x < width && 
            element.y < height) {
                newVec.add(element);
        }
    }
    vec = newVec;
}