Open-Source Internship opportunity by OpenGenus for programmers. Apply now.
Hello folks, let us sharpen your development skill by making breakout game in HTML and JS.
Table of contents
1.Introduction
2.Rules for playing breakout game
3.Approach
4.Implementation
5.Output
6.Future improvements
7.Conclusion
Introduction
By combining HTML and JavaScript, developers can create an engaging and interactive Breakout game that can be played directly in a web browser. The game utilizes the canvas element in HTML, which provides a drawing surface for graphics and animations. JavaScript is then used to handle the game logic, including the movement of the paddle and ball,and collision detection.
In this article at OpenGenus, we will explore how to create a Breakout game using HTML and JavaScript. We will dive into the implementation details. By the end of this project, you will have a fully functional Breakout game that you can play and even customize according to your preferences.
Rules for playing breakout game
- Game Setup:
- The game screen consists of a rectangular area.
- At the top of the screen, there are rows of bricks arranged in a specific pattern.
- The player controls a paddle at the bottom of the screen.
- A ball is placed on the paddle at the start of the game.
- Objective:
- The goal is to break all the bricks on the screen by hitting them with the ball using the paddle.
- The player earns points for each brick broken.
- Paddle Control:
- The player moves the paddle horizontally using left and right arrow keys.
- The paddle can only move along the bottom of the screen.
- Ball Movement:
- The ball initially rests on the paddle.
- When the game starts or after the player launches the ball, it moves upward at a specific angle.
- The ball bounces off the walls and the bricks it hits.
- The player's objective is to prevent the ball from falling below the paddle.
- If the ball hits the bottom edge of the screen, the player loses a life.
- Brick Breakage:
- When the ball hits a brick, the brick disappears, and the player earns points.
Approach
We are going to use following steps for developing our breakout game:
- HTML and CSS Setup:
- Create Brick Objects:
- Handle Paddle Movement:
- Implement Ball Movement:
- Handle Collisions:
- Update the Game Loop:
- Customize Graphics
- Handle User Input:
Overall strategy of implementation
HTML Structure:
- Create a canvas element that will serve as the game screen.
- Use CSS to style the canvas size, background, and other visual elements as needed.
- Add a score display, level display, and any other UI elements you wish to include.
JavaScript Game Initialization:
- Define variables to store game-related data, such as the canvas context, paddle position, ball position, score, lives, etc.
- Set up event listeners to capture user input, such as keyboard or touch events, for controlling the paddle.
Bricks:
- Create an array or data structure to hold information about the bricks, such as their positions, colors, and durability.
- Design a pattern for the bricks, and initialize the array accordingly.
- Implement logic to detect collisions between the ball and the bricks, updating their durability or removing them when hit.
Paddle and Ball:
- Define the paddle's initial position, size, and movement speed.
- Implement logic to move the paddle based on user input and keep it within the game screen boundaries.
- Set up the ball's initial position, speed, and angle of movement.
- Handle the ball's collision detection and response with the walls, paddle, and bricks, updating its direction and speed accordingly.
Game Loop:
- Create a game loop function that updates the game state and renders the changes on the canvas.
- Inside the game loop, handle paddle movement, ball movement, collision detection, and game logic updates.
- Continuously redraw the game screen based on the updated state.
At the end, after completion of all the steps we can achieve our final result as our basic working breakout game.
Implementation
- Set up for project
It's very simple structure, we only required "index.html" file and "script.js" file for implementation of our game logic.
Create "index.html" file and write following code
<!DOCTYPE html>
<html>
<head>
<title>Breakout Game</title>
<meta charset="UTF-8">
<style>
html, body {
height: 100%;
margin: 0;
}
body {
background: black;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<canvas width="400" height="500" id="game"></canvas>
<script src="./script.js"></script>
</body>
</html>
Html file define the basic structure of our game.
- html: The root element containing the entire HTML document.
- head: Contains metadata and script/style references.
- title: Sets the title of the page.
- meta charset="UTF-8": Specifies the character encoding of the document.
- style: Defines CSS rules to style the elements.
- body: Contains the visible content of the page.
- canvas: An HTML5 element that provides a drawable region on the page. It is used to render the game graphics.
Now, let's implement our logical part in javascript, which is majorly most important part of the breakout game.
create "script.js" file in the same folder where the index.html file is located, and write the following code.
const canvas = document.getElementById('game');
const context = canvas.getContext('2d');
- const canvas = document.getElementById('game');: Retrieves the canvas element using its ID.
- const context = canvas.getContext('2d');: Gets the 2D rendering context of the canvas, allowing drawing on it.
// each row is 14 bricks long. the level consists of 6 blank rows then 8 rows
// of 4 colors: red, orange, green, and yellow
const level1 = [
[],
[],
[],
[],
[],
[],
['R','R','R','R','R','R','R','R','R','R','R','R','R','R'],
['R','R','R','R','R','R','R','R','R','R','R','R','R','R'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['G','G','G','G','G','G','G','G','G','G','G','G','G','G'],
['G','G','G','G','G','G','G','G','G','G','G','G','G','G'],
['B','B','B','B','B','B','B','B','B','B','B','B','B','B'],
['B','B','B','B','B','B','B','B','B','B','B','B','B','B']
];
// create a mapping between color short code (R, O, G, B) and color name
const colorMap = {
'R': 'red',
'O': 'orange',
'G': 'green',
'B': 'blue'
};
Level and Brick Initialization:
- level1: An array representing the layout of bricks in the game.
- Each element in level1 represents a row of bricks, and the colors are represented by single-letter codes.
- colorMap: An object that maps the color codes to their corresponding color names.
// use a 2px gap between each brick
const brickGap = 2;
const brickWidth = 25;
const brickHeight = 12;
// the wall width takes up the remaining space of the canvas width. with 14 bricks
// and 13 2px gaps between them, thats: 400 - (14 * 25 + 2 * 13) = 24px. so each
// wall will be 12px
const wallSize = 12;
const bricks = [];
Constants and Variables:
- brickGap, brickWidth, and brickHeight: Dimensions of the bricks.
- wallSize: Width of the walls on the top and sides of the canvas.
- bricks: An array that will store individual brick objects.
// create the level by looping over each row and column in the level1 array
// and creating an object with the bricks position (x, y) and color
for (let row = 0; row < level1.length; row++) {
for (let col = 0; col < level1[row].length; col++) {
const colorCode = level1[row][col];
bricks.push({
x: wallSize + (brickWidth + brickGap) * col,
y: wallSize + (brickHeight + brickGap) * row,
color: colorMap[colorCode],
width: brickWidth,
height: brickHeight
});
}
}
Creating Brick Objects:
- Nested loops iterate over level1 to create brick objects based on their position, color, and dimensions.
- Each brick object is pushed into the bricks array, containing its position (x and y), color, and dimensions.
const paddle = {
// place the paddle horizontally in the middle of the screen
x: canvas.width / 2 - brickWidth / 2,
y: 440,
width: brickWidth,
height: brickHeight,
// paddle x velocity
dx: 0
};
const ball = {
x: 130,
y: 260,
width: 5,
height: 5,
// how fast the ball should go in either the x or y direction
speed: 2,
// ball velocity
dx: 0,
dy: 0
};
Paddle and Ball Initialization:
- paddle: Represents the game's paddle and defines its position, dimensions, and velocity (dx).
- ball: Represents the game's ball and defines its position, dimensions, speed, and velocity (dx and dy).
// check for collision between two objects using axis-aligned bounding box (AABB)
// @see https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
function collides(obj1, obj2) {
return obj1.x < obj2.x + obj2.width &&
obj1.x + obj1.width > obj2.x &&
obj1.y < obj2.y + obj2.height &&
obj1.y + obj1.height > obj2.y;
}
Collision Detection:
- collides(obj1, obj2): A function that checks for collision between two objects using the Axis-Aligned Bounding Box (AABB) algorithm.
// game loop
function loop() {
requestAnimationFrame(loop);
context.clearRect(0,0,canvas.width,canvas.height);
// move paddle by it's velocity
paddle.x += paddle.dx;
// prevent paddle from going through walls
if (paddle.x < wallSize) {
paddle.x = wallSize
}
else if (paddle.x + brickWidth > canvas.width - wallSize) {
paddle.x = canvas.width - wallSize - brickWidth;
}
// move ball by it's velocity
ball.x += ball.dx;
ball.y += ball.dy;
// prevent ball from going through walls by changing its velocity
// left & right walls
if (ball.x < wallSize) {
ball.x = wallSize;
ball.dx *= -1;
}
else if (ball.x + ball.width > canvas.width - wallSize) {
ball.x = canvas.width - wallSize - ball.width;
ball.dx *= -1;
}
// top wall
if (ball.y < wallSize) {
ball.y = wallSize;
ball.dy *= -1;
}
// reset ball if it goes below the screen
if (ball.y > canvas.height) {
ball.x = 130;
ball.y = 260;
ball.dx = 0;
ball.dy = 0;
}
// check to see if ball collides with paddle. if they do change y velocity
if (collides(ball, paddle)) {
ball.dy *= -1;
// move ball above the paddle otherwise the collision will happen again
// in the next frame
ball.y = paddle.y - ball.height;
}
// check to see if ball collides with a brick. if it does, remove the brick
// and change the ball velocity based on the side the brick was hit on
for (let i = 0; i < bricks.length; i++) {
const brick = bricks[i];
if (collides(ball, brick)) {
// remove brick from the bricks array
bricks.splice(i, 1);
// ball is above or below the brick, change y velocity
// account for the balls speed since it will be inside the brick when it
// collides
if (ball.y + ball.height - ball.speed <= brick.y ||
ball.y >= brick.y + brick.height - ball.speed) {
ball.dy *= -1;
}
// ball is on either side of the brick, change x velocity
else {
ball.dx *= -1;
}
break;
}
}
// draw walls
context.fillStyle = 'lightgrey';
context.fillRect(0, 0, canvas.width, wallSize);
context.fillRect(0, 0, wallSize, canvas.height);
context.fillRect(canvas.width - wallSize, 0, wallSize, canvas.height);
// draw ball if it's moving
if (ball.dx || ball.dy) {
context.fillRect(ball.x, ball.y, ball.width, ball.height);
}
// draw bricks
bricks.forEach(function(brick) {
context.fillStyle = brick.color;
context.fillRect(brick.x, brick.y, brick.width, brick.height);
});
// draw paddle
context.fillStyle = 'cyan';
context.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
}
Game Loop:
- loop(): The game loop function responsible for rendering the graphics and updating the game state.
- It is called recursively using requestAnimationFrame to ensure smooth animation.
- The loop clears the canvas, moves the paddle and ball according to their velocities, and handles collisions.
- It also draws the walls, ball, bricks, and paddle on the canvas using the rendering context (context).
// listen to keyboard events to move the paddle
document.addEventListener('keydown', function(e) {
// left arrow key
if (e.which === 37) {
paddle.dx = -3;
}
// right arrow key
else if (e.which === 39) {
paddle.dx = 3;
}
// space key
// if they ball is not moving, we can launch the ball using the space key. ball
// will move towards the bottom right to start
if (ball.dx === 0 && ball.dy === 0 && e.which === 32) {
ball.dx = ball.speed;
ball.dy = ball.speed;
}
});
// listen to keyboard events to stop the paddle if key is released
document.addEventListener('keyup', function(e) {
if (e.which === 37 || e.which === 39) {
paddle.dx = 0;
}
});
Keyboard Event Listeners:
- Event listeners are added to handle keyboard input.
- When the left or right arrow keys are pressed, the paddle's velocity (dx) is updated accordingly.
- When the space key is pressed, the ball is launched if it's not moving, setting its velocity (dx and dy) to move towards the bottom right.
// start the game
requestAnimationFrame(loop);
Game Initialization:
- The game loop is started by calling requestAnimationFrame(loop).
And,that's done for our game logic!
Output
Hers is what our final output looks like
Future Improvements
- Scorekeeping: The game could keep track of the player's score and display it on the screen.
- Multiple levels: The game could have multiple levels, with each level becoming more difficult.
- Power-ups: The game could include power-ups that give the player special abilities, such as the ability to destroy multiple bricks at once.
- Sound effects: The game could include sound effects to make it more immersive.
Conclusion
A basic version of the Breakout game using HTML and JavaScript. The game features a paddle, a ball, and bricks arranged in different levels.The game starts by rendering the game elements on a canvas element.Overall, this implementation provides a foundation for a simple Breakout game and can serve as a starting point for adding additional features and enhancements. It demonstrates the use of HTML canvas, JavaScript game logic, collision detection, and keyboard event handling to create an interactive gaming experience.