轨迹运动是物理学中一个非常成熟的领域,其在现实世界中有着广泛的应用。在众多应用中,轨迹运动已成为许多电脑游戏的基础。例如,著名的游戏《愤怒的小鸟》就是利用轨迹运动的原理,玩家可以通过调整角度来发射小鸟,以击中目标(城堡、物品、猪)。
在之前的文章《MVVM与HTML5/KnockoutJS》中,已经介绍了MVVM模式与SVG/KnockoutJS的结合使用,因此本文不会详细介绍SVG/MVVM/KnockoutJS的基础知识。假设已经了解HTML5和SVG的基础知识,并邀请读者查阅有关轨迹运动模拟器的论文《多层感知器作为游戏运动生成的基础》。
简化的轨迹运动方程(不考虑阻力因子、质量等物理变量)由以下方程式控制:
x = Vx * t
y = Vy * t - 0.5 * G * t^2
也就是说,物体在轨迹运动中的位置(x,y)是物体速度和重力作用的函数。物体在x方向上的速度越大,它在x轴上的移动速度就越快;物体在y方向上的速度越大,它能达到的轨迹峰值就越高。轨迹的峰值高度也受到重力的负面影响(即-G)。
编写模拟代码的第一步是创建ViewModel。在这里,将创建几个可观察变量,用于轨迹模拟。正如所想象的,需要一个坐标(x,y)来描述物体的位置。然后,需要一个变量来存储模拟时间t,Vx和Vy分别是x轴和y轴上的初始速度,g是重力。为了更准确,它应该是g-y,因为力只在y轴上有分量,但为了简化,继续称之为g。将注意到在update()函数中,力g只与y轴分量有关。
最后,在ViewModel中引入了一个名为trails的observableArray。这个数组用于存储运动的轨迹,以便可以绘制物体在2D空间中移动的每一个点,从模拟时间t=0到t=<模拟结束>。
现在ViewModel几乎完成了。现在需要定义update()函数。正如所见,update函数非常简单直接,特别是如果熟悉轨迹运动方程的话。在这个函数中,每次更新时,通过某个恒定因子更新模拟时间。这里选择0.05是任意的,以接近50ms更新周期。
每次调用这个函数时,需要更新三件事: 1. 通过Vx * t更新x。这表示物体在x轴上在最后0.05时间单位内的位移,速度为Vx。[注意:可能在想如果Vx本身有加速度怎么办?当然,可以对此进行实验] 2. 通过Vy * t和-0.5 * g * (t^2)更新y。这表示物体在y轴上在最后0.05时间单位内的位移,速度为Vy向上,同时重力作为阻力因子向相反方向移动。 3. 将最后一个点插入到trails数组中。
应该提醒,由于x、y、trails是可观察对象,因此根据可观察对象的更新方式更新这些变量。一个可观察对象是一个函数而不是一个属性,因此这样。
x(n)
更新可观察对象x为值n。
接下来,将定义View。对于模拟,需要一个模拟对象,将使用svg
有了这些svg定义,离完成模拟只有一步之遥。在定义了ViewModel和View之后,现在需要将它们绑定在一起。多亏了KnockoutJS的简单API,只需要用一行额外的代码就可以做到这一点。
现在已经准备好了模拟器,但缺少一个东西。需要一个计时器来更新模拟计时器。将使用javascript setInterval(callback, milliseconds)来实现这一点。
由于希望每隔X毫秒调用一次update()函数(选择了50),模拟循环可以很容易地通过调用来设置:
setInterval(function() { viewModel.update() }, 50);
现在模拟器循环已经设置好了,可以运行模拟器了。可以尝试不同的物理变量来在浏览器上创建一些有趣的轨迹运动。
可以尝试这个轨迹运动模拟器的实时演示版本。实时演示包含了一些额外的代码,允许交互式地修改物理变量并启动/重置模拟器。尽管如此,邀请查看实时演示的源代码,如果好奇的话。好消息是,这些额外的好处只需要一点点额外的代码。多亏了MVVM模式和KnockoutJS通过数据绑定的强大功能,数据的更新会自动刷新并呈现给UI。
下面是刚刚创建的轨迹模拟器的截图。
总结:本文展示了如何使用HTML5/SVG和KnockoutJS编写轨迹运动模拟器。人们会想知道编写这种模拟器需要多少代码,特别是对于对图形编程知之甚少的人来说。
答案是,有了HTML5/SVG和KnockoutJS,编写这种东西只需要很少的编码。记得大约10年前,当在论文“多层感知器作为游戏运动生成的基础”中工作时,不得不编写大量的C++/OpenGL代码来编写一个轨迹运动模拟器。