DEV Community

Cover image for Build a breakout game
Dhanush N
Dhanush N

Posted on • Originally published at dhanushnehru.hashnode.dev

Build a breakout game

Hey guys,

In this article I will show you how I built a breakout game using HTML canvas, CSS and Javascript. Using a single ball, the player must knock down as many bricks as possible by using the walls and/or the paddle below to hit the ball against the bricks and eliminate them.

In this game, you will have 3 lives, and you must hit the ball against the bricks and eliminate them. If you are not able to eliminate the bricks within 3 lives, then your game is over.

Why did I want to create this game ?

I want to familiarise myself with using HTML Canvas and the flexibility of building a game with it.

Setup for the project

This game is best viewed or played on a desktop computer with the help of a mouse pointer.

Let's start coding !!!

The project structure consists of only 3 files.

|__ style.css
|__ script.js
|__ index.html
Enter fullscreen mode Exit fullscreen mode

Let's begin with the program.

A simple html file with canvas defined

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Breakout Game</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>

    <canvas id="myCanvas" width="600" height="600"></canvas>

<script src="script.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

A css file for the background and defining the colors.

* {
    padding: 10;
    margin: 10;
} 

#myCanvas {
    background: #eee;
    display: block;
    margin: 0 auto;
}
Enter fullscreen mode Exit fullscreen mode

A Javascript file that defines each operation as a function.

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

var x = canvas.width/2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var ballRadius = 25;
var paddleHeight = 10;
var paddleWidth = 100;
var paddleX = (canvas.width-paddleWidth)/2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 5;
var brickColumnCount = 8;
var brickWidth = 100;
var brickHeight = 10;
var brickPadding = 7;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var score = 0;
var lives = 3;

var bricks = [];
for (c=0; c<brickColumnCount; c++) {
    bricks[c] = [];
    for (r=0; r<brickRowCount; r++) {
        bricks[c][r] = {x: 0, y:0, status: 1};
    }
}
/*
document.addEventListener("keydown", keyDownHandler);
document.addEventListener("keyup", keyUpHandler);
*/
function drawBricks() {
    for(c=0; c<brickColumnCount; c++) {
        for(r=0; r<brickRowCount; r++) {
            if(bricks[c][r].status == 1) {
                var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
                var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
                bricks[c][r].x = brickX;
                bricks[c][r].y = brickY;
                ctx.beginPath();
                ctx.rect(brickX, brickY, brickWidth, brickHeight);
                ctx.fillStyle = "#0095DD";
                ctx.fill();
                ctx.closePath();
            }
        }
    }
}

function keyDownHandler(e) {
    if(e.keyCode == 39) {
        rightPressed = true;
    }
    else if(e.keyCode == 37)  
        leftPressed = true;
    }
}

function keyUpHandler(e) {
    if(e.keyCode == 39) {
        rightPressed = false;
    }
    else if(e.keyCode == 37) {
        leftPressed = false;
    }
}
Enter fullscreen mode Exit fullscreen mode

After defining the objects as functions lets call the draw based methods to perform the individual operations such as drawing a ball, identifying the collision between the ball etc.

function drawBall() {
    ctx.beginPath();
    ctx.arc(x, y, ballRadius, 0, Math.PI*2);
    ctx.fillStyle = "#FF0000";
    ctx.fill();
    ctx.closePath();
}

function drawPaddle() {
    ctx.beginPath();
    ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
    ctx.fillStyle = "pink";
    ctx.fill();
    ctx.closePath();
}

function collisionDetection() {
    for(c=0; c<brickColumnCount; c++){
        for(r=0; r<brickRowCount; r++){
            var b = bricks[c][r];
            if(b.status  == 1) {
                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
                    dy = -dy;
                    b.status = 0;
                    score++;
                    if(score == brickRowCount*brickColumnCount) {
                        alert("YOU WIN, CONGRADULATIONS!");
                        document.location.reload();
                    }
                }
            }
        }
    }
}

function drawScore () {
    ctx.font = "16px Arial";
    ctx.fillStyle = "#0095DD";
    ctx.fillText("Score: "+score, 8, 20);
}

function drawLives() {
    ctx.font = "16px Arial";
    ctx.fillStyle = "#0095DD";
    ctx.fillText("Lives: "+lives, canvas.width-65, 20);
}
Enter fullscreen mode Exit fullscreen mode

Now lets create a draw method which combines the above functions together

function draw() {
    ctx.clearRect(0,0, canvas.width, canvas.height);
    drawBricks()
    drawBall();
    drawPaddle();
    drawScore();
    drawLives();
    collisionDetection();

    if(y + dy < ballRadius) {
        dy = -dy;
    } else if (y + dy > canvas.height-ballRadius) {
        if(x > paddleX && x < paddleX + paddleWidth) {
            dy = -dy;
        } else {
            lives--;
            if(!lives) {
                alert("GAME OVER!");
                document.location.reload();
            } else {
                x = canvas.width/2;
                y = canvas.height-30;
                dx = 2;
                dy = -2;
                paddleX = (canvas.width-paddleWidth)/2;
            }
        }
    }
    if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
        dx = -dx;
    }

    if(rightPressed && paddleX < canvas.width-paddleWidth) {
        paddleX += 7;
    }
    else if(leftPressed && paddleX > 0) {
        paddleX -= 7;
    }

    x += dx;
    y += dy;
    requestAnimationFrame(draw);
}

Enter fullscreen mode Exit fullscreen mode

Now lets add the functions to define the movement of the mouse finally.

document.addEventListener("mousemove", mouseMoveHandler);

function mouseMoveHandler(e) {
    var relativeX = e.clientX - canvas.offsetLeft;
    if(relativeX > 0+paddleWidth/2 && relativeX < canvas.width-paddleWidth/2) {
        paddleX = relativeX - paddleWidth/2;
    }
}

draw();
Enter fullscreen mode Exit fullscreen mode

The draw method actually calls a set of functions, starting from drawing the bricks to the various elements needed for the breakout game.

Conclusion 

I was able to accomplish this by dividing the elements of the game into small parts and designing the entire game by combining parts of the code with functionality to be set 

You can try playing the game here and get the source code here. Feel free to contribute incase you have any improvements to be done ✌️

Thanks for reading ❤️

Feel free to subscribe to my newsletter.
Follow me via Twitter, Instagram, or Github.

Top comments (0)