Vanilla JavaScript Breakout Game

Jazmin
5 min readOct 8, 2021

I created a vanilla JavaScript Breakout Game, similar to the Atari Breakout game from 1976, and also known as a brick breaker game. You can check out my project and play it yourself here.

Breakout game project

My project’s rules were as follows:

  • Your game should have a single screen with 8 rows of bricks, a paddle, and a ball.
  • If the ball touches the bottom of the screen, you lose a ‘life’.
  • After 5 lives, the game is over.
  • Every time the ball touches a brick, the brick disappears and the score increases.
  • The ball bounces off the paddle, the bricks, and the top/left/right edges of the screen.

When prepping for this project, I researched videos on how best to create it. The top two ways I found were using HTML5 canvas and manipulating the DOM. I first tried to create my project using canvas as I had previously worked with canvas to create a drawing web application for my 4th Flatiron School project. I quickly switched to manipulating the DOM instead as I was more familiar with it.

The first thing I did was select my color palette using coolors.co. I randomly generated color palettes until I found the one that I liked. I decided on the color palette below. As the ball, score, and lives are the most important thing to keep track of in the game, they are in the accent color — imperial red. I also wanted to differentiate the bricks from the paddle as to not look so monotonous.

Color Palette of 5 colors: 3 blues, 1 off-white, 1 red

The next thing I did was choose a google font. I wanted the game to have an old school look with a modern twist, so I decided on Press Start 2P, a google font inspired by 80s arcade games. In order to have access to the font in the project, I put the code below inside my <head> tag in index.html.

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">

In my CSS file, I inputted ‘font-family: “Press Start 2P”, cursive;’ in my * CSS selectors so that my entire project had consistent font.

The rest of my index.html file was very simple. It is made up of div containers for the game over screen and the game board, which consists of the game title, score, lives, and start game button.

<body>
<div id="game-over">
<h1 id="game-over-sign">GAME OVER</h1>
<h3 id="final-score"></h3>
</div>
<div id="game-board">
<div class="title">
<h1>Breakout Game</h1>
</div>
<div id="score">
<h3>Score: 0</h3>
</div>
<div id="life"></div>
<button id="start-game">Start Game</button>
</div>
<body>

The project also includes 3 JavaScript files - life.js, shape.js, and index.js, which deals with the logic of the game. Life.js is a class that is in charge of the heart containers on the bottom right of the game and shape.js is in charge of creating the ball, paddle, and bricks. I won’t go into detail for shape.js or index.js. As for life.js, you can see the code below:

class Life {
static lifeContainer = document.getElementById("life");
static all = []; // use this to keep track of the 5 lives

constructor() {
this.lifeElement = document.createElement("div");
this.lifeElement.className = "life";
Life.all.push(this.lifeElement);
}
putOnDom() {
Life.lifeContainer.appendChild(this.lifeElement);
};
static loseLife() {
// lose life when ball touches bottom
if (Life.all.length > 1) {
Life.lifeContainer.removeChild(Life.all.shift());
} else {
Life.lifeContainer.removeChild(Life.all.shift());
// Make gameOver screen appear
gameOver.style.display = "block";
// Populate final score on game over screen
finalScore.innerText = `Score: ${score}`;
// freezes ball position
ballCurrentXYPosition[1] = -1;
// Reset game score
score = -1;
// will increment score to 0
updateScore();
};
};
static createFiveLives() {
// create 5 lives
let left = 75;
for (let i = 0; i < 5; i++) {
let leftString = left + "%";
const heart = new Life();
heart.lifeElement.style.left = leftString;
// each life has an id between 0 and 4
heart.lifeElement.id = i;
heart.putOnDom();
left += 5;
};
};
};

This file is made up of 4 static methods (similar to Ruby class methods), an instance method, and a constructor method. When a life instance is created, a div is created with a class name of "life" and the pushed onto the static all method in order to keep track of all the lives. Giving it a class name allows me to use a CSS class selector in order to style it as a heart to give it that retro arcade feel.

.life {
position: absolute;
width: 12px;
height: 20px;
background-color: #e63946;
bottom: 1%;
transform: rotate(45deg);
border-radius: 100px 100px 7px 0;
}
.life::before {
position: absolute;
width: 12px;
height: 20px;
background-color: inherit;
content: "";
transform: rotate(90deg);
left: -35%;
top: 19%;
border-radius: 0 7px 100px 100px;
}

The putOnDom method is aptly named. It uses the lifeContainer that was retrieved in the second line of the class and appends the life instance to it. I call this method in the createFiveLives method. As the name suggests, it creates 5 lives. I decided to hardcode 5 because 5 lives was one of the requirements of this project. If I wanted the ability to create a different amount of lives, I could pass in a number argument and use that in the for loop instead of the number 5. The for loop deals with the CSS positioning of the hearts. The heart's left positioning begins at 75 and as it goes through the loop, it increments by 5 so that the next heart's left positioning is 80. This is what allows the hearts to be displayed in a straight line. I call this method in index.js.

The last method - loseLife - is also called in index.js. Once again, the name of the method describes what it does. If the player has more than one life left, a heart will be removed from the lifeContainer. If the player only has one more life left, and the ball touches the bottom of the screen, the game over screen and final score will appear. The ball’s position will be fixed and stop moving. The score on the bottom left will be reset to 0.

Overall, this was a very fun project to make. Being able to play something that you created is very rewarding.

--

--