There are many situations in game programming and animation that call for motion paths; a racing car speeding around a track or the sun slowly rising and setting. In fact, any scenario where we want a sprite to follow a predetermined path is a good fit for motion paths. In this post I will explain how to create motion paths, and how to make sprites follow them, using JavaScript and the Phaser HTML5 game framework. The special ingredients lie within the Phaser math class; more specifically within just three methods of that class.

The Interpolation Methods

Here are the three all important 'motion path' methods: linearInterpolation, bezierInterpolation and catmullRomInterpolation. Lets take a moment to consider what these methods actually do. This is important because these methods do not magically create motion paths for us; they only handle the math for us. Fortunately, they’re pretty easy to grasp once you see them in action.

Each of the interpolation methods take a first argument that will be an array of numeric values and a second argument that will be a number between 0 and 1. You can think of the former as representing a set of points residing on a path and the latter as representing some distance along that path. A code listing will make this clearer.

Listing 1 shows the math.linearInterpolation method in action. Have a look through the code in the create method and then take a look at the numbers it produces. Basically, all this code does is show linear interpolation operating over the an array of values using a different number for the distance variable at each call.

Listing 1. Looking at the numbers.

Notice how our points array consists of numbers that start off at 2 and gradually work their way up to 640. When we increase the value of the distance variable (remember, this should always be a value between 0 and 1) we 'move along' to higher numbers. In fact, at a value of 1 we are 100% of the way along and we see the last number in the points array, 640, as the result.

To really see what the math.linearInterpolation method is up to you can make things more interesting by tinkering with the code. Notice that the points array is currently nice and predictable? That is to say, we start off with a low number and gradually increase to the maximum number. That sounds too much like a straight line to me, and we don’t need motion paths to draw straight lines!

var points = [2, 128, 266, 768, 512, 640];

The points array above moves from 2 to 640, but notice that it has a value of 768 right in the middle. You can plug this into Listing 1, or simply mess with the numbers that are there already, and observe the effect on the output numbers.

Drawing Motion Paths

Ok, so the above was a bit of insight into one of the interpolation methods, but how do we use this to guide sprite movement? Simply put, we use the interpolation methods to help us the x and y coordinates of our sprites. Let’s break this down into two distinct parts to make it easier to follow: creating the motion path and then making a sprite follow it.

Creating a Motion Path.

Take a look at Listing 2 and then we will walk through the important bits. This listing shows how you might go about drawing a motion path to the screen. Of course, you usually won’t want the motion path to be visible to the end user, but in this case it will help us to visualise what we could only see as numeric output in listing 1.

Listing 2. Drawing a Motion Path

Importantly, the points in this example come from two arrays; one for our x positions and one for our y positions. I experimented with these values to get something I liked, but I made sure at the outset to start at the top left of the screen (note the 0 at the first position of each array) and to finish at the bottom right of the screen (note the games width and height values in the last position of each array). Of course, you can use whatever values you need to achieve the result you need.

Take note of the this.increment variable. We have divided 1 by the width of our game, 480 and stored the value here. This gives us a very small number, 0.002083. Our for loop executes 480 times, each time drawing the small rectangles that form our path. The math.linearInterpolation method is using the points arrays and the current value of this.increment to help us calculate where to draw.

I encourage you to tinker with this listing before moving on. Try changing values in both of the points arrays, and see what happens when you switch out math.linearInterpolation for math.bezierInterpolation and catmullRomInterpolation.

Making a Sprite Follow a Motion Paths.

Knowing what we now know, it isn’t very difficult to take it a small step further and, instead of drawing a line all at once, use the interpolation logic to make a sprite move across the screen over a period of time. Here is a code listing that does just that; pay special attention to the plot function.

Listing 2. Attaching a Sprite to a Motion Path

Much of this code is boilerplate, with some of logic managing the timer (so the animation repeats). The bit you should be interested in is this:

var px = this.math.linearInterpolation(this.points.x, this.i);
var py = this.math.linearInterpolation(this.points.y, this.i);
this.birdSprite.x = px;
this.birdSprite.y = py;
this.i += this.increment;

Make sure you are happy with the relationship between this.i and this.increment. The former starts its life at 0 but is increased by the latter each time the plot function is called. This means that we progress the sprite nicely along the 'distance' of the path.

To wrap this up, lets take a look at the result of changing the interpolation methods but leaving everything else as is.

Listing 3. Bezier Interpolation.

Listing 4. CatmullRom Interpolation.

I hope you found this post useful and easy to follow. Be sure to tinker with the code listings a bit if things are not quite sinking in. It is relatively simple stuff, but there are a few moving parts. Don't be surprised if that magical 'aha!' feeling kicks in only after some experimentation.