HTML5 Game Development Tutorial: Breakout Part III – Collisions, Scoring and Sound

Breakout v0.6 ScreenshotThis is the third in a series of tutorials on developing a full featured version of Breakout.

In the second tutorial, we used setInterval() to add some animation and capture keydown and keyup events to respond to user input.

In this tutorial, we will bring back the bricks we drew before, handle the ball colliding with these bricks, and finally increase the score when a brick gets destroyed. We will also add some sound effects to make the game more fun.

We will use the code from the last tutorial as our starting point.

Lets get started.

First we add back two lines at the beginning of the animate() function to draw the scoreboard and the bricks.

function animate () {
	context.clearRect(0,0,canvas.width,canvas.height);
					
	createBricks();
	displayScoreBoard();

Right now the ball will move over the bricks without bouncing off them.

We need the ball to reverse X direction if it hits the sides of the bricks, reverse Y direction if it hits the top or bottom of the bricks and damage the bricks every time it touches them.

Lets create functions to check whether the ball is colliding with a brick along the X or Y direction, and to damage the brick if it collides.


function collisionXWithBricks(){
    var bumpedX = false;	
	for (var i=0; i < bricks.length; i++) {
		for (var j=0; j < bricks[i].length; j++) {
			if (bricks[i][j]){ // if brick is still visible
				var brickX = j * brickWidth;
				var brickY = i * brickHeight;
				if (
				    // barely touching from left
				    ((ballX + ballDeltaX + ballRadius >= brickX) &&
		            (ballX + ballRadius <= brickX))
		            ||
		            // barely touching from right
					((ballX + ballDeltaX - ballRadius<= brickX + brickWidth)&&
					(ballX - ballRadius >= brickX + brickWidth))
					){		
					if ((ballY + ballDeltaY -ballRadius<= brickY + brickHeight) &&
						(ballY + ballDeltaY + ballRadius >= brickY)){													
						// weaken brick and increase score
						explodeBrick(i,j);

						bumpedX = true;
					}
				}
			}
		}
	}
		return bumpedX;
}				

function collisionYWithBricks(){
    var bumpedY = false;
	for (var i=0; i < bricks.length; i++) {
		for (var j=0; j < bricks[i].length; j++) {
			if (bricks[i][j]){ // if brick is still visible
				var brickX = j * brickWidth;
				var brickY = i * brickHeight;
				if (
				    // barely touching from below
				    ((ballY + ballDeltaY - ballRadius <= brickY + brickHeight) && 
				    (ballY - ballRadius >= brickY + brickHeight))
				    ||
				    // barely touching from above
					((ballY + ballDeltaY + ballRadius >= brickY) &&
					(ballY + ballRadius <= brickY ))){
					if (ballX + ballDeltaX + ballRadius >= brickX && 
						ballX + ballDeltaX - ballRadius<= brickX + brickWidth){										
						// weaken brick and increase score
						explodeBrick(i,j);							
						bumpedY = true;
					}						
				}
			}
		}
	}
	return bumpedY;
}

function explodeBrick(i,j){
	// First weaken the brick (0 means brick has gone)
	bricks[i][j] --;

	if (bricks[i][j]>0){ 
		// The brick is weakened but still around. Give a single point.
		score++;
	} else {
		// give player an extra point when the brick disappears
		score += 2;		
	}
}

The collisionXWithBricks() and collisionYWithBricks() functions return true when they bounce against a brick and automatically call explodeBrick() to weaken the brick and update the score. To start using these functions, we modify the collision checking conditions in moveBall() slightly.

// If top of the ball touches the top then reverse Y direction
if (ballY + ballDeltaY - ballRadius < 0 
	// or if ball collides in Y direction with bricks
	|| collisionYWithBricks()){
	ballDeltaY = -ballDeltaY;
}

// If side of ball touches either side of the wall then reverse X direction
	//left of ball moves too far left
if ((ballX + ballDeltaX - ballRadius < 0) ||
	//or right side of ball moves too far right
(ballX + ballDeltaX + ballRadius > canvas.width)
// or if ball collides in Y direction with bricks
|| collisionXWithBricks()
){  
	ballDeltaX = -ballDeltaX;
}

At this point, the ball bounces off the bricks as expected and weakens the brick when it hits them. Once the brick is completely destroyed, it disappears and gives the player an extra points.

Not bad. The game works fine, however there is still something missing.

A little sound tends to give players a much more immersive experience and will make the game more fun. With HTML5 Audio, implementing sound is surprisingly easy.

To play sounds, we load files using the Audio() object and play them using its play() method. Browsers are still a little inconsistent about which formats they support. The OGG file format is an open format supported by both Chrome and Firefox (my favorites), which is why we will stick with them for now.

To create the sound we place the two files at the same location as the HTML file and load them by creating new Audio() objects and storing them in variables. The OGG sound files used here are included with the source code.

var bouncingSound = new Audio("bounce.ogg");
var breakingSound = new Audio("break.ogg");

To play these sounds, all we need to do is invoke the play() method.

We can play the breaking sound whenever a brick is completely destroyed (inside the explodeBrick() function).

function explodeBrick(i,j){
	// First weaken the brick (0 means brick has gone)
	bricks[i][j] --;
				
	if (bricks[i][j]>0){ 
		// The brick is weakened but still around. Give a single point.
		score++;
	} else {
		// give player an extra point when the brick disappears
		score += 2;	
	
		breakingSound.play();
	}
}

And the bounce sound anytime we change X or Y direction for the ball (inside the moveBall() function)

function moveBall(){
// First check if we will bump into something

// If top of the ball touches the top then reverse Y direction
if (ballY + ballDeltaY - ballRadius < 0 
	// or if ball collides in Y direction with bricks
	|| collisionYWithBricks()){
	ballDeltaY = -ballDeltaY;
	bouncingSound.play();
}

// If the bottom of the ball touches the bottom of the screen then end the game
if (ballY + ballDeltaY + ballRadius > canvas.height){
	endGame();
}
// If side of ball touches either side of the wall then reverse X direction
	//left of ball moves too far left
if ((ballX + ballDeltaX - ballRadius < 0) ||
	//or right side of ball moves too far right
(ballX + ballDeltaX + ballRadius > canvas.width)
// or if ball collides in Y direction with bricks
|| collisionXWithBricks()
){  
	ballDeltaX = -ballDeltaX;
	bouncingSound.play();
}

// if bottom of ball reaches the top of paddle,
if (ballY + ballDeltaY + ballRadius >= paddleY){
	// and it is positioned between the two ends of the paddle (is on top)
	if (ballX + ballDeltaX >= paddleX && 
		ballX + ballDeltaX <= paddleX + paddleWidth){
		ballDeltaY = - ballDeltaY;
		bouncingSound.play();
	}
}

// Move the ball
ballX = ballX + ballDeltaX;
ballY = ballY + ballDeltaY;
}

That’s really all there is to it. We have a game with sound effects, animation, keyboard control and increasing scores written entirely in HTML and Javascript.

To make the game more fun, we can add more interesting brick types, sounds and game mechanics.

In my version of the game, the bricks start falling down, we have Cash bricks to give money, Bomb bricks that explode everything nearby, Laser Ammo bricks that let us shoot laser from the paddle and Spider bricks that shriek and start crawling down at the user. Check out the game to see what you think. Leave a comment if you enjoy the game.

I don’t see much point showing people how to implement the exact same features in a game, because at this point it is fairly simple to do. However if you have an interesting idea that you would like to add to the game, leave me a comment below. If we get a few interesting ideas, we can have one more tutorial where we implement the ideas and create our own new version of the game.

If not, stay tuned for my next tutorial series on how to implement a Real Time Strategy game engine entirely in HTML5 and Javascript. Check out Command and Conquer – Programming an RTS game in HTML5 and Javascript.

You can download the finished source code for this tutorial below.

Leave a Reply