Breakout 2.0

Now we’re getting somewhere.

Finch Masters
8 min readFeb 6, 2017

Catching Up

This week I went on to further explore the capabilities of the Phaser framework by implementing some features on top of the version of Breakout that I had already created. The features I added so far include:

  • sound effects when the ball collides with the player’s paddle or a block
  • lives or how many times the player can miss the ball before the game ends
  • a score that increases with each block hit
  • multiple levels
  • ball speed and angle changing based on where it hit the paddle

In addition to the new features, I reorganized the code so that it was easier to work with. If you’d like to play, the game can be played here and the code is here.

How I Reorganized

I’ve spent most of my coding career writing Object Oriented code in PHP. Because of that, I’m very used to having my classes written and separated in multiple files. In Javascript, it is entirely possible to write code in separate files, load them asynchronously, and everything works out just fine. In the case of creating states for this game, just separating them wasn’t going to cut it because they relied on the states object existing before they could be added to it and I wanted all states added to that object before any part of the game ran.

So real quick the problem is I need a Phaser.Game object created first, then a states object needs to be made, then I create as many states as I want and add them to the states object, and then I can call game.state.start() to get the ball rolling (or bouncing in this case). Code is loaded asynchronously so I can’t guarantee that the states will be made after the game object is created, so what am I supposed to do?

The answer is: use RequireJS. Using this little library, I was able to achieve the synchronous functionality required by setting a callback to be called when the asynchronous file loading was complete. Take a look:

Looks pretty simple right? I separated each of my states into its own file and RequireJS did its magic to make my life easy.

After I got the code decently organized, I went about my business writing the new features. First up? Audio.

Bleeps and Bloops

Let’s go ahead and jump on in with the sound effects since they were probably the easiest to implement.

Before we get into the code though, I’d like to point out that I had completely forgotten that music and sound effects are not free (most of the time) and I had to go find some that were freely available. It didn’t take me long before I stumbled upon Freesound and my savior: NoiseCollector. Similar sounds can be grouped into packs on Freesound and NoiseCollector uploaded the Pong softsynth pack which had exactly what I was looking for.

Alright so now for the code. We’re going to treat the sound files that we want to use almost exactly the same as we did in by loading them in the preload() function in our game state.

After we’ve loaded the audio files that we need, we’ll assign a file to an object so we can actually control when and how it plays.

In this case, I created a soundEffects object in the game state and saved each object to it for easy reference later. Once you’ve got it in an object, all you need to do is play it:

And that’s is. Really. Of course, you can mess with the volume, start playing the file from one time and end at another, and do a ton of other things with audio thanks to Phaser. For Breakout though, one bleep and one bloop is just about all you need.

No more permadeath!

The next feature that I added was a limited number of lives that the player could use up before the game ended. This eases the difficulty of the game for those who need it and provides a safety net for those who are better just in case something goes wrong.

The implementation is almost too simple to go over here, but I added lives as a member of the game state, initialized it in our create() method, and checked for it when the ball reaches the bottom of the screen:

To make it easy for the player to know how many lives they have left, I added a text counter in the top right of the screen during create() and updated it in this check.

High Score

Implementing a score system was just as easy as keeping track of the player’s lives. I added score to the game state, initialized it in create(), and updated it in update() if the ball hit a block. I kept track of the score on screen for the player just like I did with the lives.

Level Up

The level system went almost exactly as I had thought it was going to go. Previously, I had a row loop and a column loop making a bunch of blocks in the create() method. I output the x and y coordinates for each of those blocks and saved each of them as a point in an array of arrays called levels. The structure looks like this: levels[ level ][ point ][ x, y ]. I then realized that I wanted to be able to support multiple block types in the future so I updated the structure to be like this: levels[ level ][ point ][ block type, [ x, y ] ]. From there, I wrote a little function to read from the array to build a level:

Once I was able to build a level from an input array, I added a couple levels and added the following to the update() method:

The original check for if a player had won the game (this.blocks.size === 0) has been changed to check if there is another level first. If so, update the level text, stop the ball from moving, reset the ball’s position, build the level, and allow the player to launch the ball again. If there is not another level in line, the player wins.

Adding Variety

One of the features in the original Breakout that was missing from my implementation was any variability in ball speed and angle. The variability seen in the original was most often caused by where the ball had come in contact with the paddle. For my implementation, I decided that the speed and angle would be affected if the ball hit on the left or right third of the paddle and that it would stay the same if hit in the middle. Additionally, I used Math.random() to make it just a little unpredictable.

This part, for being as simple as it was, tripped me up for a bit because I had completely forgotten about setting the anchor point on the player’s paddle. I assumed that by asking for this.paddle.x I was going to get the x coordinate of the left side of the paddle.Once I had what I thought was the left side, I wanted to add 1/3 of the paddle’s width to get area within which I wanted to check for collision with the ball. That part was right, but since I set the anchor point of the paddle to be in the center, that’s what was being returned when I referenced this.paddle.x. As soon as I realized this, I adjusted the check to subtract half of the the paddle’s width from the x position and it all magically worked. Moral of the story: pay attention to your anchor points.

Easter Egg

There was one more piece to the puzzle that was missing from my game. I only had one type of block. The ball hits it and gets bounced back in the opposite direction. Simple to implement, simple to play with. I wanted to make one extra block type, and since the level implementation allowed for it easily, I decided to go for it.

I started by loading an image in create() and updated my createBlock() method to accept a key for a different sprite. Once the extra block was being built for the level I just had to add a check in the ball/block collision part of update() and check the block.key to see which type of block was hit.

I added a little special functionality for that one brick and I’m deliberately avoiding showing the code for this section because I want you to go find it and see what happens.

Shout Out

I’ve pointed to them in the past, but the people over at the Mozilla Developer Network have put up some of the most useful documentation on web development that you can find. While working through a few issues, I stumbled upon their awesome game development info. Turns out, they’ve even got a tutorial for making Breakout using Phaser so if you get stuck with what I’ve been doing, feel free to check them out.

What’s Up Next

There’s certainly more features to add to this Breakout clone, but there are other useful features of the Phaser engine that I would like to explore as well as distribution methods like Electron that I want to try out. On top that of that, I need to start learning how to create more complex graphics than just monochromatic blocks and text and I need to learn to create custom sound effects and music when I can’t find what I need available for free. The next post may not show up next week, but I think I’m going to focus my efforts on creating a more comprehensive experience from scratch.

If you have any questions, comments, or concerns just let me know. I’ll be happy to respond to anything and everything. Like, share, and follow and eventually, we’ll all be game devs.

--

--