Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML5

Trajectory Motion Simulator with HTML5/SVG/KnockoutJS

4.11/5 (2 votes)
14 Aug 2012CPOL6 min read 27.8K   359  
A simple trajectory simulation with SVG / KnockoutJS

Introduction

This article shows how one can write a simple trajectory motion simulator using SVG/KnockoutJS.

A trajectory motion is a very established body of physics that we have seen many applications in the real world. Among many real-world applications, trajectory motion has become the basis for many computer games these days. The very well known game that uses the trajectory motion is the famous Angry-bird game where a player can aim the angry birds with certain angle to create a trajectory motion to hit and crush the targets (castles, items, pigs).

Background

My previous article MVVM with HTML5/KnockoutJS should give you a kick start on MVVM with SVG/KnockoutJS. Thereby, I would not cover the basics of SVG/MVVM/KnockoutJS in great details in this article. I assume that you also know the basic of HTML5 and SVG.

I invite the reader to also check the paper on trajectory motion simulator Multilayer Perceptron as the basis for Gaming Motion Generation.

The Trajectory Motion Equations

The simplified trajectory motion (without taking the drag factor, mass and other physics variables into consideration) is governed by the following equations (wikipedia):

x = Vx . t

y = Vy . t - 0.5 . G . t^2

That is, the position of the object (x, y) in trajectory motion is a function of the velocity of the object and the gravitational force. The greater the velocity in x direction the faster the object moves in x-axis and the greater the velocity of the object in y-axis the higher that it can reach the peak of the trajectory. The peak height of the trajectory is also affected negatively by the gravitational force (i.e. -G).

Writing the Simulation Code

The first thing we would do is to create our ViewModel. Here we would create several observables variables that we will use for our trajectory simulation. As you would have imagined, that we need a coordinate (x, y) to describe the position of the object. Then, we need a variable to store the simulation time t, the Vx and Vy as the initial velocity on x-axis and y-axis respectively and the g our gravitational force. To be more accurate it should really be a g-y, since the force only have the y-axis component), but to simplify we keep referring to it as g. You will notice in the update() function that the force g is relevant only to the y-axis component.

Lastly, we introduce a trails as an observableArray in our ViewModel. This array is used for us to store the trails of the motion so that we can draw every point in 2D space for which the object has moved between simulation time t=0 up to t=<end of simulation>.

By now we almost complete our ViewModel. Now we need to define our update() function. As you can see our update function is very straight-forward, especially if you are familiar with the trajectory motion equations. In this function on each update we update our simulation time by some constant factor. Here 0.05 is chosen arbitrarily to be close with our 50ms update period.

Three things that we need to update every time we call this function:-

1. Update the x by Vx * t. This signifies the displacement of the object in x-axis in the last 0.05 time unit with the velocity of Vx. [NOTE: you might be thinking what if the Vx itself has an acceleration? surely you can experiment with that]

2. Update the y by Vy * t and - 0.5.g.(t^2). This signifies the displacement of the object on the y-axis in the last 0.05 time unit with the constant velocity Vy going upward and at the same time the the gravitational force works in the opposite way as a drag factor moving the opposite direction.

3. Insert the last point into the trails array.

I should remind you that since x, y, trails are observable objects, hence we update these variables according to how observable objects should be updated. An observable is a function not a property, thus this.x(n) updates observable x with the value n.

JavaScript
  //
  // 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);
         }
     }
}

Next, we would define our View. For our simulation, we need a simulation object and we will use svg <circle> to represent our simulation object. Additionally, to draw our simulation trails, we would create another svg <circle> that we generate through <!-- ko foreach:trails --> directive (tutorials on ko foreach can be found here). The svg <line> represents the initial velocity vector - an indicator of the initial direction of the trajectory motion (the poor man version of the Angry Bird shoot direction indicator).

HTML
<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>

With these svg definitions, we are only one step away from finishing off our simulation. After we define our ViewModel and the View, now we need to bind them together. Thanks to the simple KnockoutJS API, we only need to do this with one extra line. 

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

At this point, we have the simulator ready to go but we are missing one thing. We need a timer that updates our simulation timer. We will use javascript setInterval(callback, milliseconds) to do this.

Since we want to call our update() function every X milliseconds (50 is chosen), the simulation loop can be easily setup by calling: 

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

Now with the simulator loop is setup, we can run the simulator. You can experiment with different physics variables to create some interesting trajectory motion right on your browser.

You can try the live demo version of the Trajectory Motion simulator from this link. The live demo contains a little bit more code to allow the us to interactively modify the physics variables and start/reset the simulator. Nonetheless, I invite you to check the source code from the live demo if you are curious. The good news is that those additional benefits come only with a little extra code. Thanks to the MVVM pattern and KnockoutJS through the power of data-binding that the updates to the data is refreshed and presented automatically to the UI.

Below is the screenshot of the trajectory simulator that we have just created.

Summary

This article shows how one can write a Trajectory Motion simulator with HTML5/SVG and KnockoutJS. One will wonder how much code does it take to write this kind of simulator, especially for someone who knows little about graphics programming.

The answer is that with HTML5/SVG and KnockoutJS, it takes a trivial amount of coding to be able to create something like this. I remember about 10 years ago when I was working on my thesis "Multilayer Perceptron as the basis for Gaming Motion Generation ", I had to write a non-trivial amount of code in C++/OpenGL code to write a trajectory motion simulator.

In a reflection, this shows how much the HTML5 and web technologies have advanced that many things now can be done much faster and easier.

History

V1.0: trajectory simulation with controllable x, y, t, Vx, Vy, G variables.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)