修复碰撞检测穿透问题

3
我正在我的游戏中实现碰撞检测,但我有点难以理解如何计算在碰撞时修正重叠形状的向量。
举个例子,假设我有两个正方形squareA和squareB。对于它们两个,我都知道它们的xCo、yCo、width和height。然而,squareA正在移动,所以它有一个速度magnitude和一个速度angle。让我们假装我每秒更新一次游戏。以下是这种情况的描绘:
现在,我需要一个公式来获取修正重叠的向量。如果我将这个向量应用到红色正方形(squareA)上,它们就不会再重叠了。这就是我想要实现的内容。
有人可以帮我找出计算向量的公式吗?
如果是Java构建则得到额外奖励分数。
如果您打字回答而不是链接到碰撞检测教程,则可得到额外的奖励分数。
谢谢大家!
另外,如何计算新的速度magnitude和angle?我希望squareA沿着x轴继续移动(沿着蓝色正方形的顶部滑动)。

你真的需要做得这么精确和复杂吗?常见的方法是“尝试”再前进一步,如果发生碰撞,就停止移动的对象。即使在许多知名和独立游戏中也使用这种方法。 - libik
我确实需要它精确。例如,如果帧率低,你的方法可能会在两个方块之间留下很大的间隙。比如,在第一张图片上它可能只会停留在原地。 - Dominic Mortlock
是的,但就像我说的那样,我用我说的方法做了,它并不完美,但足够好了。然后当我玩游戏时,我惊讶地发现很多著名的游戏都使用了完全相同的方法 :)。 - libik
@libik 好的。在我的旧游戏中,我会逐渐从 x 和 y 中减少一个像素,直到它们不再碰撞。但是我正在制作的这个新游戏非常依赖于物理学。 - Dominic Mortlock
可以通过解析几何精确地完成。您知道运动向量,可以创建从源到目标正方形的线,并计算交点,因此可以精确定位这两个正方形的位置。但是,如果有多于2个物体在移动并且可以多次相互作用,我不知道该怎么办... - libik
xCo是在正方形的中心还是在某个角落? - Beta
2个回答

0
我有一个函数,大致长这个样子:
Position calculateValidPosition(Position start, Position end)
    Position middlePoint = (start + end) /2

    if (middlePoint == start || middlePoint == end)
        return start 

    if( isColliding(middlePont) )
        return calculateValidPosition(start, middlePoint)
    else
        return calculate(middlePoint, end)

我刚刚草率编写了这段代码,所以有很多改进的空间...从不将其递归开始。

当检测到碰撞时,会调用此函数,并将对象的最后一个有效位置和当前无效位置作为参数传递。 在每次迭代中,第一个参数始终是有效的(没有碰撞),而第二个参数是无效的(存在碰撞)。

但我认为这可以给您提供可能的解决方案的想法,以便您可以根据自己的需要进行调整。


0

根据您的问题描述,需要回答的是您整个应用程序。但是提供一个简单的答案也很容易。

  1. 你需要使用四叉树来划分空间。
  2. 你似乎表明只有一个对象会在检测到碰撞时被移动。(对于多个相互穿插的对象,只需对集合中的每一对对象进行修正,直到没有重叠。)
  3. 既不是弹性碰撞也不是非弹性碰撞是期望的行为。你想要简单地投影出水平速度(方块A的),所以Vx(t-1) = Vx(t+1),Vy(t-1)是无关紧要的,而Vy(t+1)=0。这里t是碰撞的时间。
  4. 方块A的重新定位很简单。
    • 将Cn定义为从A的质心到顶点n的向量(其中顶点的标记是任意的)。
    • 将A(t-1)定义为A的前一个方向。
    • 将Dn定义为A(t-1)和向量Cn的点积。
    • 将Rn定义为沿着Cn测量的A的宽度(并向质心相反方向延伸)。
    • 将Sn定义为B的膨胀半径为Rn。
    • 让j成为B的y值最高的顶点。
    • 让k成为最接近A前角的顶点[在直觉上,Dn的值表明Ck最接近于A(t-1)的平行线]。
    • 让K成为相对于k的A的反极边或顶点。

最后,将A翻译成K和j重合,并使K与Sk重合。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接