Learn how to create a breakout game using HTML, CSS, and JavaScript with this easy-to-follow tutorial. Includes source code and detailed instructions.
Table of Contents
Creating a breakout game is a fun and educational project that will help you understand the basics of HTML, CSS, and JavaScript. This tutorial will guide you through the process step-by-step, providing the source code and detailed explanations along the way. Whether you're a beginner or looking to brush up on your skills, this guide will get you started on building your own classic arcade game.
Setting Up Your Development Environment
Before we dive into the code, let's set up our development environment. You'll need a text editor (like Visual Studio Code or Sublime Text) and a web browser (like Chrome or Firefox) to test your game. Make sure you have the latest versions installed.
Start by creating a new folder for your project. Inside this folder, create three files: index.html, styles.css, and script.js. These files will hold our HTML structure, CSS styling, and JavaScript logic, respectively.
Source Code
Step 1 (HTML Code):
To start, we need a canvas element in our HTML file. This will serve as the game's playing field.
The canvas element creates a space on the webpage where the game will be drawn. The script tag at the bottom links to our JavaScript file, which will contain the game logic.
Step 2 (CSS Code):
Next, we need some basic CSS to style our game canvas. Create a styles.css file and add the following:
body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f0f0f0; } canvas { border: 2px solid #000; }
This CSS centers the canvas on the page and gives it a solid border, making it visually distinct.
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #fff;
}
canvas {
border: 1px solid #000;
}
Step 3 (JavaScript Code):
The core of our game lies in the JavaScript code. Create a script.js file and start by initializing the game variables and constants.
Initializing Variables and Constants
const canvas = document.getElementById("gameCanvas"); const ctx = canvas.getContext("2d"); canvas.width = 900; canvas.height = 600; const paddleHeight = 10; const paddleWidth = 75; let paddleX = (canvas.width - paddleWidth) / 2; const ballRadius = 10; let x = canvas.width / 2; let y = canvas.height - 30; let dx = 2; let dy = -2; let rightPressed = false; let leftPressed = false; const brickRowCount = 5; const brickColumnCount = 10; const brickWidth = 75; const brickHeight = 20; const brickPadding = 10; const brickOffsetTop = 30; const brickOffsetLeft = 30; const bricks = []; for (let c = 0; c < brickColumnCount; c++) { bricks[c] = []; for (let r = 0; r < brickRowCount; r++) { bricks[c][r] = { x: 0, y: 0, status: 1 }; } } let score = 0;
- Here, we define the canvas size, paddle dimensions, ball properties, brick settings, and initialize the game state.
Drawing the Game Elements
Next, we need functions to draw the game elements: the ball, paddle, and bricks.
function drawBall() { ctx.beginPath(); ctx.arc(x, y, ballRadius, 0, Math.PI * 2); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); } function drawPaddle() { ctx.beginPath(); ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); } function drawBricks() { for (let c = 0; c < brickColumnCount; c++) { for (let r = 0; r < brickRowCount; r++) { if (bricks[c][r].status === 1) { const brickX = c * (brickWidth + brickPadding) + brickOffsetLeft; const 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(); } } } }
- These functions will draw the ball, paddle, and bricks onto the canvas.
Implementing User Controls
We need to allow the player to move the paddle. We'll use keyboard event listeners for this.
document.addEventListener("keydown", keyDownHandler, false); document.addEventListener("keyup", keyUpHandler, false); function keyDownHandler(e) { if (e.key === "Right" || e.key === "ArrowRight") { rightPressed = true; } else if (e.key === "Left" || e.key === "ArrowLeft") { leftPressed = true; } } function keyUpHandler(e) { if (e.key === "Right" || e.key === "ArrowRight") { rightPressed = false; } else if (e.key === "Left" || e.key === "ArrowLeft") { leftPressed = false; } }
- These handlers set the appropriate flags when the arrow keys are pressed or released.
Adding Collision Detection
To make the game interactive, we need to detect collisions between the ball and the paddle or bricks.
function collisionDetection() { for (let c = 0; c < brickColumnCount; c++) { for (let r = 0; r < brickRowCount; r++) { const 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, CONGRATULATIONS!"); document.location.reload(); } } } } } }
- This function checks if the ball has hit a brick and updates the game state accordingly.
Keeping Score and Handling Game Over
Finally, we need to update the score and handle game-over conditions.
function drawScore() { ctx.font = "16px Arial"; ctx.fillStyle = "#0095DD"; ctx.fillText("Score: " + score, 8, 20); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawBricks(); drawBall(); drawPaddle(); drawScore(); collisionDetection(); if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) { dx = -dx; } if (y + dy < ballRadius) { dy = -dy; } else if (y + dy > canvas.height - ballRadius) { if (x > paddleX && x < paddleX + paddleWidth) { dy = -dy; } else { if (confirm("GAME OVER. Restart?")) { document.location.reload(); } else { document.location.reload(); } } } if (rightPressed && paddleX < canvas.width - paddleWidth) { paddleX += 7; } else if (leftPressed && paddleX > 0) { paddleX -= 7; } x += dx; y += dy; requestAnimationFrame(draw); } draw();
- The draw function clears the canvas, draws the updated game elements, and checks for collisions. It also handles the ball movement, paddle movement, and game over conditions.
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
canvas.width = 900;
canvas.height = 600;
const paddleHeight = 10;
const paddleWidth = 75;
let paddleX = (canvas.width - paddleWidth) / 2;
const ballRadius = 10;
let x = canvas.width / 2;
let y = canvas.height - 30;
let dx = 2;
let dy = -2;
let rightPressed = false;
let leftPressed = false;
const brickRowCount = 5;
const brickColumnCount = 10;
const brickWidth = 75;
const brickHeight = 20;
const brickPadding = 10;
const brickOffsetTop = 30;
const brickOffsetLeft = 30;
const bricks = [];
for (let c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (let r = 0; r < brickRowCount; r++) {
bricks[c][r] = { x: 0, y: 0, status: 1 };
}
}
let score = 0;
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if (e.key === "Right" || e.key === "ArrowRight") {
rightPressed = true;
} else if (e.key === "Left" || e.key === "ArrowLeft") {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (e.key === "Right" || e.key === "ArrowRight") {
rightPressed = false;
} else if (e.key === "Left" || e.key === "ArrowLeft") {
leftPressed = false;
}
}
function collisionDetection() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
const 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, CONGRATULATIONS!");
document.location.reload();
}
}
}
}
}
}
function drawScore() {
ctx.font = "16px Arial";
ctx.fillStyle = "#0095DD";
ctx.fillText("Score: " + score, 8, 20);
}
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function drawBricks() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
if (bricks[c][r].status === 1) {
const brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
const 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 draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScore();
collisionDetection();
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if (y + dy < ballRadius) {
dy = -dy;
} else if (y + dy > canvas.height - ballRadius) {
if (x > paddleX && x < paddleX + paddleWidth) {
dy = -dy;
} else {
if (confirm("GAME OVER. Restart?")) {
document.location.reload();
} else {
document.location.reload();
}
}
}
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
} else if (leftPressed && paddleX > 0) {
paddleX -= 7;
}
x += dx;
y += dy;
requestAnimationFrame(draw);
}
draw();
Final Output:
See the Pen Breakout Game with Vanilla JavaScript by Faraz (@codewithfaraz) on CodePen.
Conclusion:
Building a breakout game from scratch using HTML, CSS, and JavaScript is a rewarding experience. It helps you learn the basics of web development and game programming. With the skills you've gained from this tutorial, you can create more complex games and explore new programming concepts.
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊