65.9K
CodeProject 正在变化。 阅读更多。
Home

HTML5/SVG/KnockoutJS 轨迹运动模拟器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.11/5 (2投票s)

2012年8月13日

CPOL

6分钟阅读

viewsIcon

28281

downloadIcon

392

使用 SVG / KnockoutJS 的简单轨迹模拟

引言

本文展示了如何使用 SVG/KnockoutJS 编写一个简单的轨迹运动模拟器。

轨迹运动是一个非常成熟的物理学领域,我们在现实世界中有许多应用。在众多现实世界的应用中,轨迹运动如今已成为许多电脑游戏的基础。使用轨迹运动的著名游戏是著名的《愤怒的小鸟》游戏,玩家可以通过特定的角度瞄准愤怒的小鸟,创造轨迹运动来击打和摧毁目标(城堡、物品、猪)。

背景

我之前的文章 使用 HTML5/KnockoutJS 进行 MVVM 编程 应该能帮助您开始使用 SVG/KnockoutJS 进行 MVVM 编程。因此,我不会在本文中详细介绍 SVG/MVVM/KnockoutJS 的基础知识。我假设您也知道 HTML5SVG 的基础知识。

我邀请读者也查看关于轨迹运动模拟器的论文 《多层感知器作为游戏运动生成的基础》

轨迹运动方程

简化的轨迹运动(不考虑空气阻力、质量和其他物理变量)由以下方程控制(维基百科

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 轴分量相关。

最后,我们将 trails 引入 ViewModel 作为 可观察数组。此数组用于存储运动的轨迹,以便我们可以绘制物体在模拟时间 t=0 到 t=<模拟结束> 之间移动的二维空间中的每一点。

至此,我们的 ViewModel 已基本完成。现在我们需要定义我们的 update() 函数。正如您所见,我们的 update 函数非常直接,尤其是如果您熟悉轨迹运动方程。在此函数中,每次更新时,我们会将模拟时间乘以一个常数因子。这里选择 0.05 是任意的,以便接近我们的 50ms 更新周期。

每次调用此函数时,我们需要更新三件事:

1. 通过 Vx * t 更新 x。这表示物体在最后一个 0.05 个时间单位内以速度 Vx 在 x 轴上的位移。[注意:您可能会想,如果 Vx 本身有加速度怎么办?当然您可以尝试一下]

2. 通过 Vy * t 和 - 0.5.g.(t^2) 更新 y。这表示物体在最后一个 0.05 个时间单位内,以恒定速度 Vy 向上运动,同时重力以相反的方式作为阻力因子朝相反方向移动,在 y 轴上的位移。

3. 将最后一个点插入 trails 数组。

我应该提醒您,由于 x、y、trails 是可观察对象,因此我们按照可观察对象应有的方式更新这些变量。可观察对象是一个函数而不是属性,因此 this.x(n) 用值 n 更新可观察对象 x

  //
  // View Model
  //
  var ViewModel = function () {
     var self = this;
     var offset = 0;
     this.x = ko.observable(10);
     this.y = ko.observable(10);
     this.t = ko.observable(0);
     this.vx = ko.observable(6);
     this.vy = ko.observable(6);
     this.g = ko.observable(10);
     var handle;
     this.trails = ko.observableArray([]);

     // Trajectory motion formula
     // x = vx.t;
     // y = vy.t - 1/2.(g.t^2)
     this.update = function () {
         self.t(self.t() + 0.05);
         self.x(self.x() + self.vx() * self.t());
         self.y(self.y() + (self.vy() * self.t()) - (0.5 * self.g()) * Math.pow(self.t(), 2));

         this.trails.push({ x: self.x(), y: self.y() });

         if (self.y() < 0) {
             clearInterval(handle);
         }
     }
}

接下来,我们将定义我们的 View。对于我们的模拟,我们需要一个模拟对象,我们将使用 svg <circle> 来表示我们的模拟对象。此外,为了绘制我们的模拟轨迹,我们将创建另一个 svg <circle>,通过 <!-- ko foreach:trails --> 指令生成(关于 ko foreach 的教程可以在 这里 找到)。svg <line> 代表初始速度向量——指示轨迹运动初始方向的指示器(“穷人版”的 愤怒的小鸟 射击方向指示器)。

<svg id="svgRoot" 
              xmlns="http://www.w3.org/2000/svg" 
              xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- the initial velocity vector -->
    <line x1="0" y1="480" 
       data-bind="attr: {y2:(480-4*vy()),x2:4*vx()}"></line>

    <!-- the trails of the trajectory motion -->
    <!-- ko foreach:trails -->
    <circle r="1" data-bind="attr: {cx:x,cy:(480-y)}"></circle>    
    <!-- /ko -->
            
    <!-- the simulation object -->
    <circle r="4" data-bind="attr: {cx:x,cy:(480-y())}"></circle>
</svg>

有了这些 SVG 定义,我们距离完成模拟仅一步之遥。在定义了 ViewModelView 之后,现在我们需要将它们绑定在一起。得益于简单的 KnockoutJS API,我们只需添加一行即可完成此操作。

var viewModel = new ViewModel();
ko.applyBinding(viewModel);

此时,模拟器已准备就绪,但我们还缺少一件事。我们需要一个计时器来更新我们的模拟计时器。我们将使用 JavaScript 的 setInterval(callback, milliseconds) 来实现此目的。

由于我们希望每 X 毫秒(选择 50)调用一次 update() 函数,因此可以通过调用以下方法轻松设置模拟循环:

setInterval(function() { viewModel.update() }, 50);

现在模拟循环已设置,我们可以运行模拟器了。您可以尝试不同的物理变量,在浏览器中创建一些有趣的轨迹运动。

您可以通过此 链接 尝试轨迹运动模拟器的实时演示版本。实时演示包含更多代码,允许我们交互式地修改物理变量并“开始”/“重置”模拟器。尽管如此,我还是邀请您查看实时演示的源代码,如果您好奇的话。好消息是,这些额外的功能仅需少量额外代码即可实现。得益于 MVVM 模式和 KnockoutJS 的数据绑定功能,数据更新可以自动刷新并显示在 UI 中。

下面是我们刚刚创建的轨迹模拟器的截图。

摘要

本文展示了如何使用 HTML5/SVG 和 KnockoutJS 编写轨迹运动模拟器。对于那些对图形编程了解不多的人来说,人们可能会想知道编写这种模拟器需要多少代码。

答案是,使用 HTML5/SVG 和 KnockoutJS,编写这样的东西只需要很少的代码。我记得大约 10 年前,我在撰写我的论文“《多层感知器作为游戏运动生成的基础》”时,我不得不编写大量的 C++/OpenGL 代码来编写一个轨迹运动模拟器。

回想起来,这表明 HTML5 和 Web 技术取得了多么大的进步,现在许多事情都可以更快、更容易地完成。

历史

V1.0:具有可控 x、y、t、Vx、Vy、G 变量的轨迹模拟。

© . All rights reserved.