2D物理引擎:具有非弹性碰撞的弹跳球不会停止 [英] 2D Physics Engine: bouncing ball w/ inelastic collisions does not come to a stop

查看:125
本文介绍了2D物理引擎:具有非弹性碰撞的弹跳球不会停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've created a simple 2d physics engine in Java that uses circular projectiles and straight walls. Currently, with each frame, every projectile's position is advanced by velocity * (1/fps). Velocity is updated afterwards, once per frame. Collision detection defines a line in point-slope form using the previous and current position, checks if that line intersects with a wall, and if that intersection lies in between the previous position and current position, a collision is registered and the projectile's current position and velocity is updated accordingly. At the moment, there is no rotation, which is intended.

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

Now, this all works except in inelastic collisions. Currently, an inelastic collision multiplies the component of the projectile's velocity that is perpendicular to the surface it collided with by some coefficient that is less than 1.

说有一个弹丸在水平面上上下弹跳。 应该发生的是,弹丸速度的y分量随着每次弹跳而减小,从而导致弹丸的最大高度随每次弹跳而减小,最终达到可以忽略不计的程度。取而代之的是,球的最大高度减小到某个点,然后开始增加一些反弹,然后再次开始减小,进入一个恒定的周期。 结果是,球从未真正停止过,而是出现了抖动。

Say there is a projectile bouncing up and down on a horizontal surface. What should happen is that the y component of the projectile's velocity decreases with every bounce, causing the maximum height of the projectile to decrease with every bounce, eventually reaching a point where it becomes negligible. Instead, what happens is that the ball's maximum height decreases to a certain point, then starts to increase for a few bounces, starts decreasing again, entering a constant cycle. The result is that the ball never really stops, but appears to "jitter".

之所以会发生,是因为弹丸每次都以直线段运动帧,并且因为速度没有连续变化。如果下降球的帧多于上升球的帧,则对于那些多余的帧,球会加速,最终上升得比预期的高。发生的事情是,由于上述原因,球到达了一个反弹点,使它向上弹起的高度超过了应该达到的水平。当最大高度由于非弹性碰撞而再次下降时,它将再次执行相同的操作。

This happens because the projectile moves in straight line segments every frame and because velocity is not continuously changing. If there are more frames during which the ball is dropping down than there are frames during which the ball rises up, the ball is accelerated for those extra frames and it ends up going higher than it should have. What is happening is that the ball reaches a point where one bounce sends it higher up than it should have for the above reason. When the maximum height drops back down again due to the inelastic collision, it does the same thing again.

我尝试通过使球移动<$来消除这种情况。 c $ c>(v * t + 0.5 * a * t ^ 2),其中 v 是速度, a 是由于重力引起的加速度, t 1 / fps 。这行之有效,除了当反弹变得足够小时会导致使用直线的碰撞检测失败的事实。我也尝试过使用参数定义的抛物线进行碰撞检测,但是当检测弹丸之间的碰撞时,它变得令人讨厌且效率低下。如果您感到好奇,我可以更深入地说明我尝试的解决方案。

I've tried eliminating this by making the ball move by (v*t + 0.5*a*t^2), where v is velocity, a is acceleration due to gravity, and t is 1/fps. This works, except for the fact that it causes the collision detection using straight lines to fail when the bounces get small enough. I've also tried doing collision detection with parametrically-defined parabolas, but it becomes unbelievably annoying and inefficient when it comes to detecting collisions between projectiles. If you're curious, I can explain my attempted solution more in-depth.

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

Any other simple solutions you'd like to suggest?

在此先感谢,特别是如果您实际阅读了这五个段落。

Thanks in advance, especially if you actually read through those five paragraphs.

推荐答案

我会怎么做建议是如果跳动高度等于或大于您定义为高度的某个常数,则该代码块将仅 跳动。您将需要某种循环结构(或如下所述的辅助方法)来计算每次球反弹后的预计反弹高度。然后,您也许可以执行以下操作:(假设您输入了现在是弹跳方法了)

What I would suggest is to have a block of code that will bounce only if the bounce height is at or above a certain constant that you've defined as the height. You would need some sort of loop structure (or "helper" method as I did below) to calculate the projected bounce height after every bounce of the ball. Then you might be able to do something like this: (assuming that you've entered the "now it's time to bounce method")

private static final int MINIMUM_BOUNCE = 100 //arbitrary value

. . .

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

唯一的问题是如果您不终止,程序将检查它是否可以无限弹跳(如果球在基线上滚动)。

The only problem with this way is that if you do not terminate at some point, the program will be checking if it can bounce infinitely (if the ball is "rolling" on the baseline). This might cause some memory issues as it is to a certain extent an infinite loop.

为澄清起见,这可能会导致某些内存问题。 c>和 bounce()是我认为您将能够创建的方法。这有帮助吗?让我知道我是否错过了某件事或对这个问题的解释有误(我可能没有读完整篇文章)。

Just for clarification: calculateNewBounceHeight() and bounce() are methds that I assume you will be able to create. Does this help at all? Let me know if I missed something or interpreted the question wrong (I might not have read the whole thing).

这篇关于2D物理引擎:具有非弹性碰撞的弹跳球不会停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆