drew's projects
About

Coding Challenge: Atari Breakout in JavaScript

Published: Sep 21, 2023

Coding Challenge: Atari Breakout in JavaScript

I coded a web version of the Atari 2600 game, Breakout. Breakout is an iconic video game (partly designed by Apple founders Steve Jobs and Steve Wozniak) similar to the granddaddy of all popular video games, Pong. The original version of Breakout was an arcade game that came out in 1976, but I prefer the look of the Atari version that came out in 1978. It has a minimalist and retro charm to it.

I made my version of the game with JavaScript and HTML canvas. Canvas allows you to draw shapes to the screen and animate them through JavaScript code. Web tools like JavaScript and canvas are totally free to use so they provide a boundless playground of creativity accessible to anyone with a computer. I love coding with JavaScript and canvas because you can easily share your projects with anyone on the web too.

You can play the game full screen and view the complete code on Codepen: https://codepen.io/fleemaja/full/KKbZpOV. Use the arrow keys, the 'wasd' keys, mouse presses, or touches on tablet and mobile to move the paddle around. You can also play the game within this blog post in the window below:

Breakout is a very simple game so it's a good place to start with my coding journey on this blog. Breakout has only rectangles to draw on the screen and a single unchanging arena where everything happens, so it's relatively simple to think about and to implement into code. It is fascinating how a full game that was once the cutting edge of console gaming can now be made by coders as a little toy project in a couple hundred lines of code and slapped up on a website like Codepen to share with the whole world.

I implemented some changes to the original game in my version. I added a loading animation for the ball to indicate when it was about to be spat out at you. I changed the ball's color to a blinking green and white when its velocity increases to indicate speed. I made the game infinite by having unlimited levels and giving the user unlimited lives.

This blog post is not a full from the ground-up tutorial. In this post, I am going to outline the high-level steps I took to make the game, provide a couple of thoughts on some of the blocks of code, and discuss some of the challenges I faced and some of the things I learned. If you are curious about learning to do creative coding like this with JavaScript and canvas I recommend Youtube channels like Chris Courses and The Coding Train among many others. There are so many amazing learning resources on the web for coding.

When faced with the task of creating a piece of software, it is wise to think about tackling the project one little step at a time. If you break your todo list into bite sized chunks, it is much less overwhelming to approach a complicated project. Here's how I broke down this project into steps:

Steps to Make this Game

  1. setup and animate an html canvas
  2. add the user's paddle to the bottom of the screen
  3. add walls
  4. add a ball
  5. get the ball moving and reset it when it goes out of bounds
  6. get the paddle moving side-to-side through user inputs
  7. detect collisions and reverse the motion of the ball on impact with the paddle or with the walls
  8. add in rows and columns of colorful blocks
  9. remove blocks on collision with the ball and reverse the ball's motion
  10. reset the blocks when all blocks on a stage have been hit
  11. change the ball's velocity (and color) when it has hit the upper blocks or the top wall. Make the paddle smaller too.
  12. add a scoreboard and increment the score, lives lost, and levels as appropriate
  13. add loading animation for the ball launch
  14. add sound effects
  15. add a pause/play button and a mute/unmute button
  16. make sure the canvas resolution is responsive to the various possible sizes the user's browser window may be in

The game is a lot like Atari's Pong. There is a paddle, a "ball" (shaped like a square), scorekeeping, and there are walls. The ball collides off the paddle or the walls and reverses one vector of its velocity. The ball's velocity vector changes depending on where on the paddle it hit (the middle of the paddle shooting the ball straight up and the corners sending the ball at more extreme horizontal angles). The ball can fly past the player and change the score, and get reset. There are tons of game development tutorials on making Pong that cover these things.

The distinguishing thing about Breakout as compared to Pong is the rows and columns of colorful blocks. You don't play against another player, but against the unpredictability of a ball careening off walls and blocks. To setup the blocks in my version I created a Block class, setup a blocks array to hold my group of blocks, and wrote this code to fill out that array:

function setupBlocks() {
    const rowBlocks = 14;
    const rowBlocksPlusWalls = rowBlocks + 2;
    for (let row = 1; row < 7; row++) {
      for (let col = 0; col < rowBlocks; col++) {
        const w = (width / rowBlocksPlusWalls)
        const block = new Block(w, (col + 1) * w, row)
        blocks.push(block)
      }
    }
}

The blocks' widths are based on the canvas width. They get arranged on the canvas based on their column index and this width multiplier. Rows of these columns get stacked on each other and the blocks are colored according to their row index.

Once the blocks have been setup and are being animated I needed to be able to detect collisions between the ball and each block. Here's the code I wrote to do rectangular collisions between the ball and the blocks:

checkBlockCollision(ball) {
    const ballX = ball.position.x
    const ballY = ball.position.y
    const blockX = this.position.x
    const blockY = this.position.y

    if (ballY + ball.height >= blockY && ballY <= blockY + this.height) {
      if (ballX + ball.width >= blockX && ballX <= blockX + this.width) {
        this.collidedWith = true
        return true
      }
    }
    return false
}

Once the blocks could detect collisions and the ball was careening around the screen it was a matter of turning the block off by setting its "collided with" variable to true. Those blocks would no longer be drawn out to the screen or cause any further collision events to the ball.

Eventually once all the blocks have this boolean set to true, some code needs to run to reset the blocks:

if (blocks.length > 0 && blocks.every(b => b.collidedWith === true)) {
    if (ball.position.y > height / 2) {
        scoreboard.updateLevel();
        blocks.forEach((b) => {
            b.collidedWith = false
        })
    }
}

This code only runs once the blocks array has been setup and checks when every block has been collided with. It updates the level and resets all blocks once the ball moves below the top half of the canvas (to allow the blocks time to setup while the ball is on its way down to the paddle).

So, we can arrange a big group of colorful blocks and interact with them in this way. This is the distinguishing feature of Breakout, but I had much more challenging parts of this project to code. Some challenges I faced:

  • I created my own font that looks like the cool retro Atari font by drawing out all of the numbers programmatically with JavaScript and canvas rectangles. It works like an old digital alarm clock with the number eight having all possible rectangles and the other numbers having some of the rectangles deactivated.
  • I spent a long time trying to find a JavaScript library to use for the sound effects. All of them were either extremely complicated or had clippy synth sounds on Firefox and I struggled to figure out why. I ended up using p5.js's sound library, which is user friendly and did the job. p5 is a JavaScript library for creative coding.
  • I made a loading animation that is an enlarged outline of the ball in the middle of the canvas that shrinks a little bit through each frame of animation until it disappears. The ball then gets released to the player.
  • I made my own pause/play and mute/unmute buttons with canvas. I drew out the shapes using simple rectangles, triangles, and arcs. I then detected when the user's mouse was within the button's area to change the cursor to a hand indicating it was clickable and used mouse press events to allow the user to click the "buttons".
  • I made the whole game responsive for any sized browser window by setting the dimensions of the canvas on page load and by setting all size related variables as ratios of these dimensions.

I enjoyed completing this coding challenge. I think Atari Breakout is still a great game nearly 50 years after its release. I had fun replicating the minimalist design of the colorful blocks and the simple number font. I haven't done much coding with sound effects, and this was a reminder that I have a ton to learn about sound design in computer programs. My code is very messy and it needs to be refactored, but I'm proud that I committed to fully replicating this game for the web and adding my own design elements to it. I am looking forward to doing more game development and creative coding in the future.