【问题标题】:Collision Detection working half the time碰撞检测工作一半的时间
【发布时间】:2011-05-25 02:57:53
【问题描述】:

我正在尝试检查两个数组之间的碰撞,一个是移动矩形,另一个是固定边界(试图让矩形从墙上反弹)。

问题是我编写了一个嵌套的 for 循环,它似乎适用于 4 个边界中的 2 个。我的循环没有达到所有可能的组合吗?

这是我的循环:

for(int n=0;n<_f;n++){
   for(int m=0;m<_b;m++){
       if(farr[n].inter(barr[m]))
           farr[n].setD();
   }
}

_f 计算移动的矩形(从 0 开始并在每个添加后增加),_b 计算边界。 inter() 是我用来检测碰撞的一种方法,它在我程序的所有其他部分都有效。

任何帮助将不胜感激, 提前谢谢!!!

public boolean inter(Rect rect){
    if(Rect.intersects(rect, rec))
        return true;
    else
        return false;
}

setD() 方法:

public void setD(){
    if(_d==0)
        _d=2;
    if(_d==1)
        _d=3;
    if(_d==2)
        _d=0;
    if(_d==3)
        _d=1;
    }

使用_d的move方法:

public void moveF(){
    if(_d==0){_l+=_s;_r+=_s;}
    if(_d==1){_t+=_s;_b+=_s;}
    if(_d==2){_l-=_s;_r-=_s;}
    if(_d==3){_t-=_s;_b-=_s;}
}

_l 是左侧,_t 是顶部,_r 是右侧,_b 是底部,_s 是每次迭代移动多少像素(在所有情况下都设置为 1)

【问题讨论】:

  • 在两次评估之间你的对象是否有可能穿透墙壁?
  • 我不这么认为,我是在低速测试它们,可能至少要经过 10 次迭代才能穿过墙壁
  • 在您循环时是否有另一个线程正在修改数组?
  • 它适用于哪两个边界?可能在同一轴上的那些?或者也许那些没有通过原点?如果你削减到一个对象,你仍然看到问题吗?如果是这样,您可以在问题墙附近启动它,然后按一个键激活每个时间步长,同时观察日志输出
  • 稍后执行循环的方法告诉移动的矩形移动。边界都是不同尺寸的矩形,但工作的边界是覆盖整个屏幕左侧和整个屏幕顶部。

标签: android collision-detection


【解决方案1】:

假设 _f、_b、farr 和 barr 在循环执行期间不改变,您的循环只检查所有组合一次。那么你如何“检查一些碰撞两次”? setD() 会做一些偷偷摸摸的事情吗?你的意思是一旦一个矩形碰撞就不需要检查更多的边界?如果是这样,可以用一个简单的 break 语句来解决。否则,您的 inter() 方法可能存在问题,与它是否似乎在其他地方工作无关。你能发布你的inter实现吗?

还有另一个问题的可能性,即假设离散空间中的连续属性。正如我惊人的 ascii 艺术(标题:球和墙)技能所展示的......

第一帧:

o__|_

第 2 帧:

_o_|_

第 3 帧:

__o|_

第 4 帧:

___|o

注意球穿过了墙壁!在任何框架中,球都没有与墙壁相交。如果您每帧移动的距离可能与移动对象的特征大小大致相同或更大,则会发生这种情况。这很难通过简单的交叉点检查来检查。您实际上需要检查球在帧之间占据的路径。

如果您的矩形和障碍没有旋转,这仍然是一个相当容易的检查。使用两个框架之间移动矩形的边界矩形并将其与障碍相交。

其他想法:

  1. 你是双重碰撞,两次切换方向。

  2. 您的矩形位于两个不同的坐标空间中。

  3. 其他一些螺纹正在拧紧你的直肠。

但基本上,您的代码看起来不错。你有多少个长方形?你能把它们做成不同的颜色吗?然后,在你的循环中,当你碰撞时,调用 setD 并输出碰撞矩形的颜色,以及它在哪里。然后,当您发现问题时,终止代码并查看输出。如果你连续看到两次碰撞(导致矩形两次切换方向),你就会发现你的错误。如果您处于两个不同的坐标空间中,输出坐标也可能会有所帮助。

如果是线程问题,那么是时候重温关键部分了。

发现你的错误:

public void setD(){
    if(_d==0)
        _d=2;
    if(_d==1)
        _d=3;
    if(_d==2)
        _d=0;
    if(_d==3)
        _d=1;
    }

每一个都需要 else if,否则你在同一个调用中更新 0 变成 2 和 然后 2 变成 0。

【讨论】:

  • setD() 方法只是改变矩形移动的方向。此外,矩形移动非常缓慢,我看到它们在边界内进行多次迭代。我也相信一开始我检查矩形1是否与边界1碰撞,然后检查边界1是否与矩形1碰撞
  • @Brian:如果 farr 是矩形而 barr 是障碍物,那么当 n=1 和 m=1 时,您只需检查一次碰撞。这在外循环的生命周期中发生一次。如果您也有barr[n].inter(farr[m]) 检查,那么您将进行双重检查。但是,根据您对inter() 的实现,您可能需要 进行此检查。这就是为什么我问你是否会发布代码。
  • 我在原帖中添加了 inter() 方法,它只允许我在非矩形类中使用 intersects() 方法
  • 我假设 rec 是 Rect 类型的成员字段?不是您的问题,而是提示:将方法主体缩短为 return Rect.intersects(rect, rec); 我稍后会更仔细地研究一下。
  • 它似乎只在矩形从下方或从右侧接近边界时才有效=/我迷路了,错误可能在代码中的其他地方。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
相关资源
最近更新 更多