Trigonometry for Animation

Vectors

For people who have seen Despicable Me you should be aware that a vector has both magnitude and direction.

Magnitude relates to how far the vector travels and direction relates to the angle of the vector.

We have made use of simple vectors in GPE for example.

pen.south(10);

  • South determines the direction of the vector
  • 10 sets the magnitude of the vector

The following are examples of different vectors.

The length of the line indicates how far the vector travels (the magnitude) and the slope of the line indicates the angle of the vector (the direction).

So how are the two measured / represented?

The magnitude of the vector is typically measured in how fast a shape is moving in pixels per frame.

In the first part of this work we looked at the moving square…

The section of code that makes the square move in this case is as follows…

x++ will move the square one pixel at a time. To make the square move faster we could modify the code like so…

In this case the square would move three pixels at a time. (Magnitude)

The square in this example is moving along a horizontal line. Which in this case is zero radians. (Direction)

This may seem strange at first.

We are typically taught to understand angles in terms of degrees.

Zero degrees at 12 o’clock 90 degrees at 3 and so on.

The problem is that JavaScript doesn’t operate in these terms.

JavaScript uses the more mathematically correct unit for angles called a radian.

One radian is calculated as the distance around the circle equal to the radius.

The other issue is that we start zero radians at three o’clock rather than 12 o’clock.

What you will find is that you are not accustomed to thinking in terms of radians.

The Arc Method

To draw circles in JavaScript we draw Arcs.

The Arc method accepts the following parameters

  • X The x coordinate of the arc
  • Y The y coordinate of the arc
  • R The radius of the circle

The radius being the distance from the centre of the circle to the edge.

Start AngleHow far round the clock face in radians the arc starts from (0 is 3 O’clock

End AngleHow far round the clock in radians the arc needs to travel

Counter clockwiseOptional parameter that sends the arc anti clockwise

To create a circle wesetthe start angle to 0 and the end angle to 2*Math.PI (Which in radians is the size of the circumference of a circle.)

(Do remember though that even though we may still work with degrees that zero degrees starts at 3 not 12 o’clock.)

Working with Vectors

At some point we are going to want to make a sprite travel from point A to point B at a specified speed per frame.

We need to know how to perform the calculations to make this happen.

If you want the saucer to travel faster along the x axis simply increase the value of the increment.

OK we now have the square following a vector (per frame) like so…

What if we wanted to make the box do the following?

As we have seen above we make x velocity and y velocity the value of 1.

Now here comes the problem.

The question is what values do we need to increase the x and y coordinates for a 25 degree angle with a magnitude of 1 pixel?

To move the shape 1 pixel magnitude from A to B we need to know how much to add to the x axis and how much to add to the y axis.

Fortunately the clue to how this is in the diagram above.

If we join up the arrows above we end up with a right angled triangle.

The nice thing about right angled triangles is that they are mathematically predictable allowing us to calculate the values of VX and VY.

So step 1 some basic rules of right angled triangles

Firstly right angled triangles have as the name suggestshave a right angle in them.

The side opposite the right angle is called the hypotenuse...

The side opposite the angle is called the opposite side

The remaining side is called the adjacent side...

The nice thing about right angled triangles is that they are mathematically predictable.

If we know a limited amount of information about them we are able to calculate the information we don’t know using SOHCAHTOA.

Sine=Length of the Opposite Side / Hypotenuse

Cosine=Length of the Adjacent Side / Hypotenuse

Tangent=Length of the Opposite Side / Adjacent (We wont need this formula)

What do we know?

We know the length of the Hypotenuse (1 pixel)

Cosine=Length of the Adjacent Side / 1

Sine=Length of the Opposite Side / 1

If we know the above formulas we may transform them to work out the length of the adjacent side (VX) and the opposite side (VY).

Length of the Adjacent Side = Cosine * Hypotenuse

Length of the Opposite Side = Sine * Hypotenuse

Or

Length of the Adjacent Side = Cosine * 1

Length of the Opposite Side = Sine * 1

To convert the angle from degrees to radians (which JavaScript needs to know) we apply the following formula.

Radians = Degrees * PI / 180

So 25 degrees translates to 0.4363323129985824 radians

So…

Length of the Adjacent Side = Cosine(0.4363323129985824) * 1

Length of the Opposite Side = Sine(0.4363323129985824) * 1

Gives us…

0.9063077870366499 = Cosine(0.4363323129985824) * 1

0.42261826174069944 = Sine(0.4363323129985824) * 1

Therefore…

vx = 0.9063077870366499 pixels per frame

vy = 0.42261826174069944 pixels per frame

Fortunately when it comes to it the computer will perform the calculations for us.

Rotation

For this example we will look at the JavaScript program arrow and box available from the module web site called Arrow and Box

Arrow and box consists of two sprites arrow and box

Arrow sits in the middle of the screen always pointing at the box.

Box travels around the screen bouncing off the sides of the canvas.

As a UML class box looks like this...

As a UML class arrow looks like this...

We will use this example to see how rotation works and also examine a few other things along the way.

Let’s assume that the two sprites have been set up – we won’t get involved with their internal workings. Do take some time looking at the code though in your own time.

The next thing is to set up an HTML page with the standard issue JavaScript structure...

This won’t do anything interesting as we are simply setting up the structure.

The next step is to tell the HTML about the sprites we wish to use in the animation...

We will start with setting up the box on the canvas.

The following code does this

This code creates a new instance of the Box class called box, sets the X and Y coordinates to 80 & 40 px and draws the box on the canvas.

The result looks like this...

Next we want to set the box moving.

To do this we need to use the velocity of the box both for x and y axis like so...

If we look inside the class definition for the box object we will see that the private data members for VX and VY have been set like so...

So if we run the program now we should see the box (per frame) travel 3.5 px to the right and 3 px down the canvas like so...

When it hits the edge it vanishes off the canvas – not the result we are after.

What we want it to do is bounce off the sides of the canvas.

To do this we need to ask the questions has the x position exceeded the left and right of the canvas or has the y position exceeded the top and bottom of the canvas.

If either of the above conditions is true we need to reverse the velocity accordingly.

The following code will do this...

Notice how we need to take into account the width of the box otherwise the box will momentarily disappear when it hits the right or bottom edge.

This should enable the box t bounce around the canvas.

Having set the box bouncing around the canvas we now need to set the arrow such that it always points at the box.

We need to create a new arrow object...

Next we position it at the middle of the canvas...

Now we add code to draw the arrow...

This will set up both box and arrow however the arrow will not yet point at the box.

The last step is to set the rotation for the arrow.

There are two stages to setting up the angle of rotation.

First we need to know where the box is with reference to the arrow.

The arrow having a fixed position is always at 300,300.

We may obtain the X and Y coordinates of the box from the two properties.

If we look at this as a triangle we get the following...

Does this look familiar? It should. Again using right angled triangles we are able to calculate the angle of rotation (in radians).

Fortunately there is a handy JavaScript function that does this for us.

First we calculate the difference between the x ,y of the box and the x, y of the arrow.

This gives us dy and dx

If arrow is at 300,300 and box is at 200,400

dx = -100

dy = 100

Now that we know the length of the two sides of the triangle...

We may now feed these two values into the Math.atan2 function.

Math.atan2(dy, dx);

Like so...

This will calculate the angle of rotation to make the arrow always point at the box.