HTML5 Canvas [169]
The extra pixels of padding added to eliminate clipping during frame rotation poses a small problem for collision detection. In the Chapter 8 version of the game, we used the width and height values for bounding box collision detection. We will not use those values in this new version because we have created two new variables to use for collision detection: hitWidth and hitHeight. Instead of setting these values to 32, they are 24. This new smaller value makes our collision detection more accurate than if we used the entire tile width and height.
The new boundingBoxCollide() algorithm
All the other game objects will also have new hitWidth and hitHeight attributes. We will modify the boundingBoxCollide() function from Geo Blaster Basic to use these new values for all collision testing:
function boundingBoxCollide(object1, object2) {
var left1 = object1.x;
var left2 = object2.x;
var right1 = object1.x + object1.hitWidth;
var right2 = object2.x + object2.hitWidth;
var top1 = object1.y;
var top2 = object2.y;
var bottom1 = object1.y + object1.hitHeight;
var bottom2 = object2.y + object2.hitHeight;
if (bottom1 < top2) return(false);
if (top1 > bottom2) return(false);
if (right1 < left2) return(false);
if (left1 > right2) return(false);
return(true);
}
Next, we will take a quick look at how we will use these same ideas to render the rest of the game objects with the new tile sheets.
Rendering the Other Game Objects
The rocks, saucers, missiles, and particles will all be rendered in a manner similar to the method implemented for the player ship. Let’s first look at the code for the saucer’s render function.
Rendering the saucers
The saucers do not have a multiple-cell tile sheet, but to be consistent, we will render them as though they do. This will allow us to add more animation tiles for the saucers later:
function renderSaucers() {
var tempSaucer = {};
var saucerLength = saucers.length-1;
for (var saucerCtr=saucerLength;saucerCtr>=0;saucerCtr--){
//ConsoleLog.log("saucer: " + saucerCtr);
tempSaucer = saucers[saucerCtr];
context.save(); //save current state in stack
var sourceX = 0;
var sourceY = 0;
context.drawImage(saucerTiles, sourceX, sourceY, 30, 15,
tempSaucer.x,tempSaucer.y,30,15);
context.restore(); //pop old state on to screen
}
}
There is no need to actually calculate the sourceX and sourceY values for the saucer because the saucer is only a single tile. In this instance, we can just set them to 0. We have hardcoded the saucer.width (30) and saucer.height (15) as an example, but with all the rest of the game objects, we will use the object width and height attributes rather than literals.
Next, let’s look at the rock rendering, which varies slightly from both the player ship and the saucers.
Rendering the rocks
The rock tiles are contained inside three separate tile sheets based on their size (large, medium, and small), and we have used only five tiles for each rock. The rocks are square with a symmetrical pattern, so we only need to precreate a single quarter-turn rotation for each of the three sizes.
Here is the renderRocks() function. Notice that we must “switch” based on the scale of the rock (1=large, 2=medium, 3=small) to choose the right tile sheet to render:
function renderRocks() {
var tempRock = {};
var rocksLength = rocks.length-1;
for (var rockCtr=rocksLength;rockCtr>=0;rockCtr--){
context.save(); //save current state in stack
tempRock = rocks[rockCtr];
var sourceX = Math.floor((tempRock.rotation) % 5) * tempRock.width;
var sourceY = Math.floor((tempRock.rotation)