HTML5 Canvas [170]
switch(tempRock.scale){
case 1:
context.drawImage(largeRockTiles, sourceX, sourceY,
tempRock.width,tempRock.height,tempRock.x,tempRock.y,
tempRock.width,tempRock.height);
break;
case 2:
context.drawImage(mediumRockTiles, sourceX,
sourceY,tempRock.width,tempRock.height,tempRock.x,tempRock.y,
tempRock.width,tempRock.height);
break;
case 3:
context.drawImage(smallRockTiles, sourceX,
sourceY,tempRock.width,tempRock.height,tempRock.x,tempRock.y,
tempRock.width,tempRock.height);
break;
}
context.restore(); //pop old state on to screen
}
}
In the renderRocks() function, we are no longer using the rock.rotation attribute as the angle of rotation as we did in Geo Blaster Basic. Instead, we have repurposed the rotation attribute to represent the tile id (0–4) of the current tile on the tile sheet to render.
In the Chapter 8 version, we were able to simulate faster or slower speeds for the rock rotations by simply giving each rock a random rotationInc value. This value, either negative for counterclockwise or positive for clockwise, was added to the rotation attribute on each frame. In this new tilesheet-based version, we only have five frames of animation, so we don’t want to skip frames because it will look choppy. Instead, we are going to add two new attributes to each rock: animationCount and animationDelay.
The animationDelay will represent the number of frames between each tile change for a given rock. The animationCount variable will restart at 0 after each tile frame change and will increase by 1 on each subsequent frame tick. When animationCount is greater than animationDelay, the rock.rotation value will be increased (clockwise) or decreased (counterclockwise). Here is the new code that we will have in our updateRocks() function:
tempRock.animationCount++;
if (tempRock.animationCount > tempRock.animationDelay){
tempRock.animationCount = 0;
tempRock.rotation += tempRock.rotationInc;
if (tempRock.rotation > 4){
tempRock.rotation = 0;
}else if (tempRock.rotation <0){
tempRock.rotation = 4;
}
}
You will notice that we have hardcoded the values 4 and 0 into the tile id maximum and minimum checks. We could have just as easily used a constant or two variables for this purpose.
Rendering the missiles
Both the player missiles and saucer missiles are rendered in the same manner. For each, we simply need to know the tile id on the four-tile particleTiles image representing the tile we want to display. For the player missiles, this tile id is 1; for the saucer missile, the tile id is 0.
Let’s take a quick look at both of these functions:
function renderPlayerMissiles() {
var tempPlayerMissile = {};
var playerMissileLength = playerMissiles.length-1;
//ConsoleLog.log("render playerMissileLength=" + playerMissileLength);
for (var playerMissileCtr=playerMissileLength; playerMissileCtr>=0;
playerMissileCtr--){
//ConsoleLog.log("draw player missile " + playerMissileCtr)
tempPlayerMissile = playerMissiles[playerMissileCtr];
context.save(); //save current state in stack
var sourceX = Math.floor(1 % 4) * tempPlayerMissile.width;
var sourceY = Math.floor(1 / 4) * tempPlayerMissile.height;
context.drawImage(particleTiles, sourceX, sourceY,
tempPlayerMissile.width,tempPlayerMissile.height,
tempPlayerMissile.x,tempPlayerMissile.y,tempPlayerMissile.width,
tempPlayerMissile.height);
context.restore(); //pop old state on to screen
}
}
function renderSaucerMissiles() {
var tempSaucerMissile = {};
var saucerMissileLength = saucerMissiles.length-1;
//ConsoleLog.log("saucerMissiles= " + saucerMissiles.length)
for (var saucerMissileCtr=saucerMissileLength;
saucerMissileCtr >= 0;saucerMissileCtr--){
//ConsoleLog.log("draw player missile " + playerMissileCtr)
tempSaucerMissile = saucerMissiles[saucerMissileCtr];
context.save(); //save current state in stack
var sourceX = Math.floor(0 % 4) * tempSaucerMissile.width;
var sourceY = Math.floor(0 / 4) * tempSaucerMissile.height;
context.drawImage(particleTiles, sourceX, sourceY,
tempSaucerMissile.width,tempSaucerMissile.height,