如何用代码模拟自由落体

 

 

当学习图形化编程(比如 Python 或者 Scratch)时,能写出模拟自然界的物理现象会很有趣,比如最常见的小球自由落体现象。为了写出逼真的小球下落轨迹,首先要了解背后的原理。

目录

原理

我们的图形化程序是基于帧来显示动画的。每隔一段时间,屏幕内容更新一次,称为一帧。为了模拟出自由落体的动画,我们的程序需要计算出每帧小球出现的位置。

想象一下用一个照相机,在小球下落过程中,每隔一段等长的时间,对小球的位置拍个照片。经过一段时间后,这些照片上小球的位置,就是我们要计算的数值。

模型

最简单的模型,是小球从静止状态自由下落。将重力加速度记为 g0g0 ,我们知道在任意时刻 tt,小球的速度是

v(t)=g0t=g0nTv(t)=g0t=g0nT

TT 为相邻两帧的间隔时间。上式中 g0g0, TT 都为常量,我们可以合并为一个新的常量 g1g1,这样 v(n)v(n) 构成了一个离散序列:

 

v(n)=g1nv(n)=g1n

或者

v(n)=v(n−1)+g1(1)(1)v(n)=v(n−1)+g1

速度 v(n)v(n) 是个等差数列,随时间变化的曲线如下图中的红线:

xyOLFhacks.com

为了简化问题,假设第 nn 帧到第 n+1n+1 帧之间,小球保持 v(n)v(n) 匀速,那么在两帧之间走过的路程为

Δy(n)=v(n)T=g1nT=gnΔy(n)=v(n)T=g1nT=gn

这里得到了第 nn 帧内,小球走过的路程。而第 nn 帧的小球位置 y(n)y(n) 是前 nn 帧内走过路程的累积:

y(n)=y(n−1)+gn(2)(2)y(n)=y(n−1)+gn

这里 gg 是一个常量,和真正的重力加速度的数值 9.8m/s29.8m/s2 已经没有关系,但是仍然起到了加速度的作用:这个值越大,小球下落的越快。位置 y(n)y(n) 的级差是等差数列,随时间变化的曲线如下图中的红线:

xyOLFhacks.com

这个曲线近似是抛物线 。在连续时间模型下,y(n)y(n) 的级差对应路程 s(t)s(t) 的导数,也就是瞬时速度 v(t)v(t). 级差是等差数列,则对应瞬时速度 v(t)v(t)是线性递增函数。

更深入的研究,请参看 蛙跳积分法 。

实现

用下面的伪代码可以实现上面的 (2)(2) 式:

var y=0, n=0, g=1
while(小球未落地)
    y+=(n++)*g

这就是自由落体的代码实现。如下图所示:

(点击动画重新播放)

落地反弹

如何模拟当小球接触到地面后的反弹?

理想条件下,小球弹起的能量保持不变,速度数值不变,方向变为竖直向上。为了便于计算速度,将 上节的下落过程 改写为下面的伪代码:

var y=0, v=0, g=1
while(小球未落地)
    v+=g
    y+=v

这里 位置 yy 和速度 vv 是量纲不同的变量,不能直接相加,但这里这么写纯粹为了计算数值,效果和 上节 相同。接下来可以写小球反弹的场景:

var y=0, v=0, g=1
while(true)
    if(小球触碰地面){
        v=-v
    }
    v+=g
    y+=v

效果如下图:

考虑损耗

由于摩擦的存在和小球的形变,反弹的一瞬间,有能量的损失,所以速度从数值上会减少。假设减少的数量和速度成正比,则剩余的速度是原速度乘上一个常数,记为 f,0<f<1f,0<f<1,那么上面的伪代码就变为:

var y=0, v=0, g=1, f=0.6
while(true)
    if(小球触碰地面){
        v=-f*v
    }
    v+=g
    y+=v

效果如下图:

(点击动画重新播放)

(完)

 

 

 

转载:https://www.lfhacks.com/t/simulate-gravity#bounce

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值