在 Canvas 上,我有一个球在重力作用下落到地球
vy += gravity
ball.y += vy
我希望球弹起来,所以我实现了一个近似解决方案来检测球是否已经越过了地面的边界,如果是,则将其位置重置到地面,并将其速度翻转为负值方向。
if (ball.y + ball.radius > bottom) {
ball.y = bottom - ball.radius;
vy *= -1;
但是,我希望这是 100% 准确的。要执行此操作,ball.y 需要稍微高于地面,并且它的速度将略小于 -vy,因为重力已经开始减慢它的速度。我怎样才能计算出这些更准确的值?
距地面的距离为ball.y + ball.radius - bottom
。所以必须有一个公式将其转换为距地面的距离,我认为是 ball.y = (2 * bottom) - ball.y - 2*ball.radius;
这就是我陷入困境的地方。到目前为止我是对的吗?我现在需要计算新的速度。我确信这是可能的,但我就是无法理解它。有人可以帮忙吗?
最佳答案
这是一个完整的演示,演示了重力和弹跳物理原理:
代码是不言自明的,但进行模拟的主要部分是更新函数,其中包含以下代码:
// calculate new position
ball.x += ball.vx;
ball.y += ball.vy;
// bounce Y (don't bounce on top)
if (ball.y >= bottom - ball.radius) {
ball.y = bottom - ball.radius; // (!) GROUND LIMIT
ball.vy = -(ball.vy * ball.elasticity);
}
// bounce X
if ((ball.x >= right - ball.radius) || (ball.x <= left + ball.radius)) {
ball.x = (ball.x < (left + ball.radius) ? (left + ball.radius) : (right - ball.radius));
ball.vx = -(ball.vx * ball.elasticity);
}
// compute gravity
ball.vy += gravity;
// compute frictions
ball.vx *= airDrag;
ball.vy *= airDrag;
if (ball.y >= (bottom - ball.radius)) {
ball.vx *= groundFriction;
}
上面的代码添加了三个不同的物理变量,以创建更真实的模拟:
ball.elasticity
:恢复系数;airDrag
:阻力系数;groundFriction
:在地面上移动时施加的摩擦力。
以上所有变量均由 0 到 1 之间的值表示。最接近 1 的值意味着弹性更大、空气阻力更小且摩擦更小。最接近 0 的值意味着弹性较小、空气阻力较大且摩擦力较大。
高级物理模拟 - 如果您受到鼓励并且对物理和数学有基本的掌握:
如果您想要更真实的模拟,您可以使用 drag equation 动态更新 airDrag
。
另一项改进是使用基于数值积分的更准确算法来计算速度。这是一个很好的例子,比较了游戏开发中最常用的集成方法:http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/#
您还可以使用物理引擎,如 box2d-web如果您需要更复杂的模拟。
关于canvas - 弹跳速度计算、与地面碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17471241/