乒乓球物理问题

18

我有一个问题,但我不知道该如何描述它,所以我画了一张图。

乒乓球物理图

正如你看到的,当检测到碰撞时,球会反弹。不要在意角度-我只是这样画的。 但有时候球会穿过球拍,并离开另一边。

为什么会这样?因为当我检测到碰撞时,我将vx更改为-vx。那么在这种情况下应该怎么办?也更改y吗?但是如何检查球打到球拍的哪一侧?

或许有其他想法?

5个回答

29

这对于编写乒乓球克隆游戏的人来说是一个很常见的问题。解决方案是,在检测到碰撞时,不仅要反转速度,还要改变球的位置,以便它不会与挡板相交。

否则,球可能会被卡在挡板内部,每一帧都不断地抵消vx = -vx = vx = -vx。 直到它的y动量将其移动到足够高或低的位置才能逃脱。


你能给我解释一下吗?:> - zarcel
1
当检测到碰撞时,您需要设置球的x位置;仅更改速度是不够的。球的最左像素应出现在挡板最右位置的右侧。 - Jeff Linahan
1
基本上,当您检测到碰撞时,球可能会与挡板相切或实际上相交。因此,您的第一步必须不仅是反转速度,而且沿着新矢量推动球,直到它不与挡板相交。您需要在“原子”步骤中执行此操作,在将控制返回到常规球移动循环之前完成。 - Martin DeMello

10
有几个原因可能会导致问题。
特别地,如果球每个“tick”或“frame”可以行进超过一个像素,则在检测到碰撞时,它可能已经与挡板相交了多个像素。
然后通过改变其速度来反弹球离开挡板,但是根据新的角度,球完全离开挡板可能需要几帧的时间。所以,在下一帧中,球仍然相交,并且你又反转了速度。这种意外的情况可能会导致球最终从另一侧离开挡板,似乎直线飞过去。
当首次检测到相交时,您可能希望在挡板和球的组合上放置一个“一段时间内不要碰撞”的标志。
作为相关问题,如果球的速度足够快(尤其是当其x-分量最高时,例如当球几乎完全水平行驶时,因此可以穿过最少的挡板),实际上可能没有任何帧球物理上与挡板相交。
所有这些都取决于您的代码,我们无法看到。不过,以上内容应该能给您一些想法。

4
“暂停碰撞”的标记可以被处理为简单的状态机。当检测到碰撞时,如果处于正常状态,则应用反弹并转换到“碰撞”状态。在“碰撞”状态下,不应用任何反弹-只需保持在碰撞状态直到不再检测到碰撞,然后转换回正常状态。 效果是-反弹只能在至少经过一帧的非碰撞时间后才能重复。 - user180247
@Steve314:+1 是的,这就是我处理它的方式。 - Lightness Races in Orbit
3
理论上,球永远不可能连续两次击中同一球拍/墙壁,对吗?因此,如果您保存了它最后击中的物体,您可以忽略随后对同一物体的击中。 - André Paramés
@André:这是另一种不错的方法,与Steve的方法相差不远。 - Lightness Races in Orbit
我的方法受到的一项批评是,它可能会在两个连续帧中与两个不同的对象发生碰撞时产生混淆,例如球棒然后是上/下墙壁。要处理这种情况需要更复杂的状态。一种可能性就是正如André所描述的那样。 - user180247

0

你的精彩绘图向我展示了你没有检测到垂直碰撞。你应该对y坐标做与x坐标相同的处理。


实际上,我是这样做的。当检测到碰撞时,我将速度设置为0,然后它在绘图中的两种情况下都停止了。 - zarcel

0
这通常是由球的移动过快引起的。在一个帧中,它正在朝墙壁移动,下一个帧它已经被放置在墙壁后面。碰撞就是没有发生。您可以通过沿着球的轨迹更远地查看并检查障碍物来消除这种情况。

0
我在制作乒乓球游戏时找到的一个解决方案是,在检测到与左挡板碰撞时使用vx = abs(vx),而在检测到与右挡板碰撞时使用vx = -abs(vx)。这可以确保球只反弹一次,消除了多次反弹造成的球在挡板内部移动的问题。

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