4

我用 Java 创建了一个简单的 2d 物理引擎,它使用圆形射弹和直墙。目前,每一帧,每个射弹的位置都会提前velocity * (1/fps). 速度随后更新,每帧一次。碰撞检测使用先前和当前位置以点斜率形式定义一条线,检查该线是否与墙壁相交,如果该交叉点位于先前位置和当前位置之间,则记录碰撞并且射弹的当前位置和速度会相应更新。目前,没有预期的旋转。

现在,除了非弹性碰撞之外,这一切都有效。目前,非弹性碰撞将弹丸速度的垂直于其碰撞表面的分量乘以某个小于 1 的系数。

假设有一个弹丸在水平面上上下弹跳。应该发生的是弹丸速度的 y 分量随着每次弹跳而减小,导致弹丸的最大高度随着每次弹跳而减小,最终达到可以忽略不计的点。取而代之的是,球的最大高度降低到某个点,然后开始增加几次反弹,再次开始降低,进入一个恒定的循环。结果是球从未真正停止,而是似乎“抖动”。

发生这种情况是因为弹丸每帧都沿直线段移动,而且速度不是连续变化的。如果球落下的帧数多于球上升的帧数,则球会为这些额外的帧加速,最终会飞得比应有的更高。正在发生的事情是,球到达一个点,由于上述原因,一次反弹将其发送到比它应该具有的更高的位置。当最大高度由于非弹性碰撞再次下降时,它再次做同样的事情。

我尝试通过让球移动 来消除这种情况(v*t + 0.5*a*t^2),其中v是速度,a是重力加速度,并且t1/fps。这是可行的,除了当反弹变得足够小时,它会导致使用直线的碰撞检测失败。我也尝试过使用参数定义的抛物线进行碰撞检测,但在检测射弹之间的碰撞时,它变得令人难以置信的烦人和低效。如果您好奇,我可以更深入地解释我尝试的解决方案。

您还想提出其他简单的解决方案吗?

在此先感谢您,尤其是如果您真正阅读了这五个段落。

4

1 回答 1

0

我的建议是有一个代码块,只有当反弹高度等于或高于您定义为高度的某个常数时才会反弹。您需要某种循环结构(或我在下面所做的“辅助”方法)来计算每次球反弹后的预计反弹高度。然后你也许可以做这样的事情:(假设你已经输入了“现在是时候反弹方法”)

private static final int MINIMUM_BOUNCE = 100 //arbitrary value

. . .

if(calculateNewBounceHeight() >= MINIMUM_BOUNCE) {
    bounce();
} else {
    // terminate program?
    // notify user?
    // etc.
}

这种方式的唯一问题是,如果您没有在某个点终止,程序将检查它是否可以无限反弹(如果球在基线上“滚动”)。这可能会导致一些内存问题,因为它在一定程度上是一个无限循环。

只是为了澄清:calculateNewBounceHeight()并且bounce()是我认为您将能够创建的方法。这有帮助吗?让我知道我是否遗漏了某些内容或对问题的解释有误(我可能没有阅读全文)。

于 2015-05-12T11:59:11.630 回答