You are previewing HTML5 Canvas.

# Game Object Physics and Animation

All of our game objects will move on a two-dimensional plane. We will use basic directional movement vectors to calculate the change in the `x` and `y` coordinates for each game object. At its very basic level, we will be updating the delta x (`dx`) and delta y (`dy`) of each of our game objects on each frame to simulate movement. These `dx` and `dy` values will be based on the angle and direction in which we want the object to move. All of our logical display objects will add their respective `dx` and `dy` values to their `x` and `y` values on each frame of animation. The player ship will not use strict `dx` and `dy` because it needs to be able to float and turn independently. Let’s take a closer look at the player movement now.

## How Our Player Ship Will Move

Our player ship will change its angle of center axis rotation when the game player presses the left and right arrow keys. When the game player presses the up arrow key, the player ship will accelerate (thrust) in the angle it is facing. Because there is no friction applied to the ship, it will continue to float in the current accelerated angle until a different angle of acceleration is applied. This happens when the game player rotates to a new angle and presses the up (thrust) key once again.

### The difference between facing and moving

Our player ship can rotate to the direction it is facing while it is moving in a different direction. For this reason, we cannot simply use classic `dx` and `dy` values to represent the movement vector on the x and y axes. We must keep both sets of values for the ship at all times. When the player rotates the ship but does not thrust it, we need to draw the ship in the new rotated angle. All missile projectiles the ship fires must also move in the direction the ship is facing. On the x-axis, we will name this value `facingX`; on the y-axis, it’s `facingY`. `movingX` and `movingY` values will handle moving the ship in the direction it was pointed in when the thrust was applied. All four values are needed to thrust the ship in a new direction. Let’s take a look at this next.

### Thrusting in the rotated direction

Once the ship is rotated to the desired direction, the player can thrust it forward by pressing the up arrow key. This thrust will accelerate the player ship only while the key is pressed. Since we know the rotation of the ship, we can easily calculate the angle of the rotation. We will then add new `movingX` and `movingY` values to the ship’s `x` and `y` attributes to move it forward.

First, we must change the rotation value from degrees to radians:

`var angleInRadians = rotation * Math.PI / 180;`

You have seen this before—it’s identical to how we calculated the rotation transformation before it was applied to the player ship.

Once we have the angle of the ship’s rotation, we must calculate the `facingX` and `facingY` values for this current direction. We only do this when we are going to thrust because it is an expensive calculation, processor-wise. We could calculate these each time the player changes the ship’s rotation, but doing so would add unnecessary processor overhead:

```facingX = Math.cos(angleInRadians);

Once we have values on the x and y axes that represent the direction the player ship is currently facing, we can calculate the new `movingX` and `movingY` values for the player:

```movingX = movingX+thrustAcceleration*facingX;
movingY = movingY+thrustAcceleration*facingY;```

To apply these new values to the player ship’s current position, we need to add them to its current `x` and `y` positions. This does not occur only when the player presses the up key. If it did, the player ship would not float; it would only move when the key was pressed. We must modify the `x` and `y` values on each frame with the `movingX` and `movingY` values:

```x = x+movingX;
y = y+movingY;```

### Redrawing the player ship to start at angle 0

As you may recall, when we first drew the image for our player ship, we had the point end (the top) of the ship pointing up. We did this for ease of drawing, but it’s not really the best direction in which to draw our ship when we intend to apply calculations for rotational thrust. The pointing-up direction is actually the `-90` (or `270`) degree angle. If we want to leave everything the way it currently is, we will need to modify the `angleInRadians` calculation to look like this:

`var angleInRadians = (Math.PI * (player.rotation -90 ))/ 180;`

This is some ugly code, but it works fine if we want our player ship to be pointing up before we apply rotation transformations. A better method is to keep the current `angleInRadians` calculation but draw the ship pointing in the actual angle `0` direction (to the right). Figure 8-5 shows how we would draw this.

The drawing code for this direction would be modified to look like this:

```//facing right
context.moveTo(−10,−10);
context.lineTo(10,0);
context.moveTo(10,1);
context.lineTo(−10,10);
context.lineTo(1,1);
context.moveTo(1,−1);
context.lineTo(−10,−10);```

## Controlling the Player Ship with the Keyboard

We will add in two keyboard events and an array object to hold the state of each key press. This will allow the player to hold down a key and have it repeat without a pause. Arcade games require this type of key-press response.

### The array to hold our key presses

An array will hold the `true` or `false` value for each `keyCode` associated with key events. The `keyCode` will be the index of the array that will receive the `true` or `false` value:

`var keyPressList = [];`

### The key events

We will use separate events for both key down and key up. The key `down` event will put a `true` value in the `keyPressList` array at the index associated with the event’s `keyCode`. Conversely, the key `up` event will place a `false` in that array index:

```document.onkeydown = function(e){

e=e?e:window.event;
//ConsoleLog.log(e.keyCode + "down");
keyPressList[e.keyCode] = true;
}

document.onkeyup = function(e){
//document.body.onkeyup=function(e){
e = e?e:window.event;
//ConsoleLog.log(e.keyCode + "up");
keyPressList[e.keyCode] = false;
};```

### Evaluating key presses

Our game will need to include code to look for `true` (or `false`) values in the `keyPressList` array, and use those values to apply game logic:

```if (keyPressList[38]==true){
//thrust
var angleInRadians = player.rotation * Math.PI / 180;

movingX = movingX+thurstAcceleration*facingX;
movingY = movingY+thurstAcceleration*facingY;
}

if (keyPressList[37]==true) {
//rotate counterclockwise
rotation-=rotationalVelocity;
}

if (keyPressList[39]==true) {
//rotate clockwise
rotation+=rotationalVelocity;;
}```

Let’s add this code to our current set of rotation examples and test it out. We have made some major changes, so Example 8-8 presents the entire HTML file once again.

Example 8-8. Controlling the player ship

```<!doctype html>
<html lang="en">
<meta charset="UTF-8">
<title>CH8EX8: Ship Turn With Keys</title>
<script type="text/javascript">

canvasApp();

}

function canvasApp(){

var theCanvas = document.getElementById("canvas");
if (!theCanvas || !theCanvas.getContext) {
return;
}

var context = theCanvas.getContext("2d");

if (!context) {
return;
}

//canvasApp level variables

var rotation = 0;
var x = 50;
var y = 50;
var facingX = 0;
var facingY = 0;
var movingX = 0;
var movingY = 0;
var width = 20;
var height = 20;
var rotationalVelocity = 5; //how many degrees to turn the ship
var thrustAcceleration = .03;
var keyPressList = [];
function drawScreen() {

//check keys

if (keyPressList[38]==true){
//thrust
var angleInRadians = rotation * Math.PI / 180;

movingX = movingX+thrustAcceleration*facingX;
movingY = movingY+thrustAcceleration*facingY;

}

if (keyPressList[37]==true) {
//rotate counterclockwise
rotation −= rotationalVelocity;
}

if (keyPressList[39]==true) {
//rotate clockwise
rotation += rotationalVelocity;;
}

x = x+movingX;
y = y+movingY;

// draw background and text
context.fillStyle = '#000000';
context.fillRect(0, 0, 200, 200);
context.fillStyle = '#ffffff';
context.font = '20px _sans';
context.textBaseline = 'top';
context.fillText  ("Player Ship - key turn", 0, 180);

//transformation
var angleInRadians = rotation * Math.PI / 180;
context.save(); //save current state in stack
context.setTransform(1,0,0,1,0,0); // reset to identity

//translate the canvas origin to the center of the player
context.translate(x+.5*width,y+.5*height);

//drawShip

context.strokeStyle = '#ffffff';
context.beginPath();

//hardcoding in locations
//facing right
context.moveTo(-10,-10);
context.lineTo(10,0);
context.moveTo(10,1);
context.lineTo(-10,10);
context.lineTo(1,1);
context.moveTo(1,-1);
context.lineTo(-10,-10);

context.stroke();
context.closePath();

//restore context
context.restore(); //pop old state on to screen
}

const FRAME_RATE = 40;
var intervalTime = 1000/FRAME_RATE;
setInterval(drawScreen, intervalTime );

document.onkeydown = function(e){
e = e?e:window.event;
//ConsoleLog.log(e.keyCode + "down");
keyPressList[e.keyCode] = true;
}

document.onkeyup = function(e){
//document.body.onkeyup = function(e){
e = e?e:window.event;
//ConsoleLog.log(e.keyCode + "up");
keyPressList[e.keyCode] = false;
};

}

</script>
<body>
<div style="position: absolute; top: 50px; left: 50px;">
<canvas id="canvas" width="200" height="200">
Your browser does not support HTML5 Canvas.
</canvas>
</div>
</body>
</html>```

Once this file is run in a browser, you should be able to press the left and right keys to rotate the ship on its center axis. If you press the up key, the ship will move in the direction it is facing.

## Giving the Player Ship a Maximum Velocity

If you play with the code in Example 8-8, you will notice two problems:

1. The ship can go off the sides of the screen and get lost.

2. The ship has no maximum speed.

We’ll resolve the first issue when we start to code the complete game, but for now, let’s look at how to apply a maximum velocity to our current movement code. Suppose we give our player ship a maximum acceleration of `2` pixels per frame. It’s easy to calculate the current velocity if we are only moving in the four primary directions: up, down, right, left. When we are moving left or right, the `movingY` value will always be `0`. If we are moving up or down, the `movingX` value will always be `0`. The current velocity we are moving on one axis would be easy to compare to the maximum velocity.

But in our game, we are almost always moving in the x and y directions at the same time. To calculate the current velocity and compare it to a maximum velocity, we must use a bit more math.

First, let’s assume that we will add a maximum velocity variable to our game:

`var maxVelocity = 2;`

Next, we must make sure to calculate and compare the `maxVelocity` to the current velocity before we calculate the new `movingX` and `movingY` values. We will do this with local variables used to store the new values for `movingX` and `movingY` before they are applied:

```var movingXNew = movingX+thrustAcceleration*facingX;
var movingYNew = movingY+thrustAcceleration*facingY;```

The current velocity of our ship is the square root of `movingXNew^2 + movingYNew^2`:

`var currentVelocity = Math.sqrt ((movingXNew*movingXNew) + (movingXNew*movingXNew));`

If the `currentVelocity` is less than the `maxVelocity`, we set the `movingX` and `movingY` values:

```if (currentVelocity < maxVelocity) {
movingX = movingXNew;
movingY = movingYNew;
}```