HTML5 Canvas [135]
Playing the game
Now the game is ready to play. STATE_PLAYING calls the drawScreen() function, which is the heart of Space Raiders. The first part of this function simply moves the missiles and aliens on the screen. Moving the missiles is quite easy. We loop through the array (backward), updating the y property of each with the speed property. If they move off the top of the screen, we remove them from the array. We move through the array backward so that we can splice() array elements out of the array and not affect loop length. If we did not do this, elements would be skipped after we splice() the array:
for (var i=missiles.length-1; i>= 0;i−−) {
missiles[i].y −= missiles[i].speed;
if (missiles[i].y < (0-missiles[i].height)) {
missiles.splice(i,1);
}
}
Drawing the aliens is similar to drawing missiles—with a few exceptions. Aliens move left and right, and when they reach the side of the canvas, they move down 20 pixels and then reverse direction. To achieve the reversal in direction, multiply the speed property by -1. If the aliens are moving to the right (speed = 2), this will make the speed = -2, which will subtract from the x position and move the aliens to the left. If the aliens hit the left side of the canvas, the speed property will again be multiplied by -1 (-2 * -1), which will equal 2. The alien will then move to the right because 2 will be added to the x value for the alien each time drawScreen() is called:
//Move Aliens
for (var i=aliens.length−1; i>= 0;i−−) {
aliens[i].x += aliens[i].speed;
if (aliens[i].x > (theCanvas.width-aliens[i].width) || aliens[i].x < 0) {
aliens[i].speed *= -1;
aliens[i].y += 20;
}
if (aliens[i].y > theCanvas.height) {
aliens.splice(i,1);
}
}
The next step in drawScreen() is to detect collisions between the aliens and the missiles. This part of the code loops through the missiles array backward while nesting a loop through the aliens array. It will test every missile against every alien to determine whether there is a collision. Since we have already covered the hitTest() function, we only need to discuss what happens if a collision is detected. First, we call the play() function of the explodeSound. This is the second critical line of code in this iteration of Space Raiders, as it plays (or attempts to play) the explosion sound every time a collision is detected. After that, it splices the alien and missile objects out of their respective arrays, and then breaks out of the nested for:next loop. If there are no aliens left to shoot, we set the appState to STATE_RESET, which will add more aliens to the canvas so the player can continue shooting:
missile: for (var i=missiles.length−1; i>= 0;i−−) {
var tempMissile = missiles[i]
for (var j=aliens.length-1; j>= 0;j−−) {
var tempAlien =aliens[j];
if (hitTest(tempMissile,tempAlien)) {
explodeSound.play();
missiles.splice(i,1);
aliens.splice(j,1);
break missile;
}
}
if (aliens.length <=0) {
appState = STATE_RESET;
}
}
The last few lines of code in drawScreen() loop through the missiles and aliens arrays, and draw them onto the canvas. This is done using the drawImage() method of the context object, and the x and y properties we calculated earlier. Finally, it draws the playerImage on the canvas, and the function is finished:
//Draw Missiles
for (var i=missiles.length−1; i>= 0;i−−) {
context.drawImage(missileImage,missiles[i].x,missiles[i].y);
}
//draw aliens
for (var i=aliens.length−1; i>= 0;i−−) {
context.drawImage(alienImage,aliens[i].x,aliens[i].y);
}
//Draw Player
context.drawImage(playerImage,player.x,player.y);
Like we stated previously, Space Raiders is not a full game. We have only implemented enough to get the player to shoot missiles so we can play the shoot sound, and to detect collisions so we can play the explode sound.
Iteration #1: Playing Sounds Using a Single Object
We just described the first iteration of the dynamic audio code. It works by attempting to call the play() function of both shootSound and explodeSound as often as necessary. This appears to