Hugo’s Game Tutorial v3.4
Sound Appendix

This is an addition to the game tutorial that explains how to add sounds to your game. Of course, some of this will need to be adapted to your game context. The triggering of the sounds will probably be different for your game play. Remember the concept of moment in your game. You will need to place the code to start your sounds at the right moment in the code.

Summary

Here is a summary of what you need to introduce sounds into your game. Each part will be explained in more details below.

You will find an example of a game with sounds here. It might be a good idea to open this game in a separate tab and keep it there while you read this page. I will refer to it throught this tutorial, and my code examples come directly from this game.

Sound Files

It may seem obvious but to play a sound in your game, you need to provide a sound file. For this game, you can find those online. Browsers are able to play a variety of sound file formats: MP3, OGG, AIFF, WAVE, etc. I recommend MP3. Those files are compressed and quality is decent (usually).

There are many places online where you can find free sound clips, even whole background songs. Use a search engine. You can of course create your own sounds too. Avoid popular, published music in your game. Your game should not play classics by The Weeknd, Drake and friends, nor the latest hit from Ariana Grande or Billie Eilish. Dynamic instrumentals usually work best for backgrounds. But you may want to set a darker ambiance with slower music. Keep in mind that music and sounds establish a mood, and they are part of the design of your product.

Load the sounds in HTML

You will need to load your sound clips in the HTML file of your game. Sounds are assets, like images. I’ll explain below how to do this.

Setup the sounds in JS

Once you have the code in the HTML to load the sound files, you will need to set them up in the JS. This is very similar to the way we have handled images in this game.

Note that background music and sound effects will be treated a bit differently. You’ll see.

Trigger the sounds

When you want the sound to play in your game, you will need to call a trigger to play it. So you need to know when the sound must play: when you hit a baddy, when the game ends, when the player moves to a certain area of the canvas, etc.

LOAD SOUND FILES

Once you have determined when you will have sounds in your game, and you have selected the sound files you want to use, you need to load them in the HTML.

I suggest you place the sound files themselves like you would images: in a sub folder from the root of your game folder. You can place the sounds in the images/ folder. It does not matter.

After collecting the files, you need to load them in the code. Here’s an example of the HTML you need to load a sound:

<audio id="sample">
  <source src="audio/sample.mp3" type="audio/mp3">
</audio>

Notice the <audio> and <source> tags; you need both. You start with an audio element, and you provide the source file.

The attributes here are important.

The <audio> tag needs to have an id. This will be used in the JS to refer to this sound bite specifically. Make this id something you can remember: win, gameOver, goody, level, etc.

The <source> tag has two attributes. The src sets the source file for the sound, just like an image. And the type sets the type of sound file: audio/mp3, audio/wav, etc. Usually, the type is audio slash the extension of the file name. If you are not sure of the type, look online or ask your teacher (that’s me).

Example

In the game example I linked above, I have setup three sounds. A clip when you collect a goody, a win sound, and a background loop.

The code below is in the index.html file. Notice that it is written above the gameBox div that contains the game. It is important to place the audio elements in the HTML before the script tag that loads the JS code. Otherwise, your JS will not have access to the sounds. I have included an example sound in WAVE format below so you can see what it looks like. The other two are MP3.

<audio id="goody">
  <source src="audio/eat.wav" type="audio/wav">
</audio>
<audio id="winBell">
  <source src="audio/levelup.mp3" type="audio/mp3">
</audio>
<audio id="background">
  <source src="audio/Legowelt_HauntedArp.mp3" type="audio/mp3">
</audio>

HANDLE THE SOUNDS IN JS

Just like we did with the images, we will use a preloading system for the sounds to prevent errors. This is especially useful, in this case, when your background clip is a heavy file and pleople play your game on their mobile with a bad connection. You want them to be able to play while the sound is being downloaded.

So the code will look like below. Remember we have three sounds: "goody", "winBell", and "background". Note that I have added line numbers here for reference in my discussion below, they are on different lines in the code file itself. And of course, DO NOT INCLUDE THOSE NUMBERS IN YOUR CODE.

This code should be written right after the similar blocks used for the images, just before defining the objects. It starts at line 39 in the sample game.

 1 //Prepare sound clips
 2 var goodyAudioReady = false;
 3 var goodyAudio = document.getElementById("goody");
 4 goodyAudio.oncanplay = function () {
 5   goodyAudioReady = true;
 6 }
 7 
 8 var winAudioReady = false;
 9 var winAudio = document.getElementById("winBell");
10 winAudio.oncanplay = function () {
11   winAudioReady = true;
12   winAudio.volume = 0.6;
13 }
14 
15 var bgAudioReady = false;
16 var bgAudio = document.getElementById("background");
17 bgAudio.oncanplay = function () {
18   bgAudioReady = true;
19   bgAudio.loop = true;
20   bgAudio.volume = 0.8;
21 }
22 var bgPlaying = false;

Look at this code. It looks very similar to the images. But not exactly the same. Notice at lines 3, 9, and 16 instead of creating a new element, we make a reference to the element we have written in the HTML. Note the IDs. Also, you will notice that the command to turn the Ready variables to true is .oncanplay instead of .onload. This is because of the way sounds are loaded: the browser can start playing a sound before it is fully downloaded, this is called streaming (you may have heard of this, now you know how streaming can be handled in JS).

I have added some options too. For example, at line 12, I set the volume of the winBell. You can do this if your sound is too loud. You want all the sounds in your game to have similar strengths. Volume = 1 is the clip at its normal strength, it is the default. You can set the volume lower than 1, but not louder.

The background

The background clip is a little bit different, it needs its own small section. First, it has one more option: the loop is set to true at line 19. This makes the sound play on and on until you stop it.

But the background sound has another important extra feature. Notice at line 22, we create a variable that will determine if the background is playing: bgPlaying = false. This is important because without this condition, the background would start playing in multiple instances, one on top of each other creating a crazy sonic mess. You will see later how we manage this condition, but remember that we want the background to start playing only once.

I will repeat this later, but note that most browsers do not allow sounds to play by default when a page is loaded. For this we make the background song play whenever the player starts to play. You cannot make it run automatically.

PLAY THE SOUNDS

The last thing we need to do is start playing the sounds at the right moment. You should already have determined this when you were planning your sounds. So you need to identify where in your code you will call the commands to start playing each sound.

This of course will be different in each of your games. In my example, it goes like this:

  • The goodyAudio will play when the player collides with a goodie. So, the code will be in the main() function, inside the goodies loop, and inside the collision test.
  • The winAudio will play when the player has collected all goodies, when they win. So, the code will be in the main() function, inside the checkWin moment.
  • The bgAudio will start playing (and start looping) when the player first moves. Remember that browsers do not like auto playing sounds. This is because of abuse by advertisers. Many browsers will refuse to play a sound without first registering a user input. So, an option is to start the background loop at the first user interaction. And, in this game, this is when the player clicks any arrow on the keyboard or touches a button. So, the code will be in the keydown and touchstart event listeners. We also want the background to stop playing when the player wins.

goodyAudio

Whenever you want to play a sound, like for painting an image, you need to check if it is ready to play. And if it is, then you call the play() command to start playing.

So we want to play this sound when the player collides with a goodie. In the example game, the goodies loop is at line 194, and the collision test block starts at line 195. So the code to play the sound goes right in there, at line 197. And it looks like this.

if (goodyAudioReady) {
  goodyAudio.play();
}

Go see in the example game code where exactly this is. Remember that in your game, it can be at a different place. The whole goodies loop block, with the sound code, looks like this. (Yours will be different, focus on the new audio code. In colour.)

//check collisions
for (var i in goodies) {
  if (checkCollision(player,goodies[i])) {
    goodies.splice(i,1);
    if (goodyAudioReady) { //check if sound is ready
      goodyAudio.play();   //play sound
    }
  }
}

winAudio

The win sound will be triggered when the game is finished, when all the goodies have been collected. This happens, in the code, in the first moment of the main() function: the checkWin() condition. (at line 159 in the example) Within this block, we first paint the win image and then, at line 168 in the example, we play the winAudio.

Note that we also stop the bg loop at the same time. There is no stop() command in audio objects in JS. So here we use pause(). Code looks like this.

if (winAudioReady) {
  bgAudio.pause();
  winAudio.play();
}

bgAudio

Lastly, we want to start looping the background sound at the first interaction of the user. Again, the browser does not play sounds automatically, so we make it happen when the user presses a key on the keyboard or touches a button. So we will add the code to play the bg in the keydown event listener. (line 81 in the example game)

Remember that for the background, we have an extra condition to prevent it from playing multiple times. So not only will we check that the sound is ready to play, but we will also check if it is already playing.

//Play bg music only once
if (!bgPlaying && bgAudioReady) {
  bgAudio.play();
  bgPlaying = true;
}

Here !bgPlaying means, in English: “bgPlaying is false” (notice the exclamation point). So if bgPlaying is false and bgAudioReady is true, play bgAudio, and set bgPlaying to true. That last bit is to make sure it does not play multiple layers of the sound.

Again, this code is placed in the event listener for the keydown. That block will look like this. (Audio code in colour.) This is just an excerpt, not the whole block.

// Handle keyboard controls
addEventListener("keydown", function (e) {
  //Play bg music only once
  if (!bgPlaying && bgAudioReady) {
    bgAudio.play();
    bgPlaying = true;
  }
  
  //Keystrokes
  if (e.keyCode == 38) { // UP
    vX = 0;
    vY = -player.speed;
  }

... ... ...


You will need to place the same code in the event listener for the touchstart so the sound plays on mobile. (line 113) But keep in mind that mobile browsers are even more picky than desktop browsers when it comes to sounds. So it may not work. Don’t worry about it. Of course, there are ways of making sure that the sound will play, but I try to keep all this simple for you.

CONCLUSION

That’s it. That’s how you manage sounds in your game. Remember: You need sound files. You load these in the HTML using <audio> and <source> tags. You prepare them in the JS with a ready variable. You setup the background with a variable checking if it is playing. And you trigger the sounds at the right moment in your game code.

It is not more complicated than this.

Resources

I know you want me to give you links to free sound archives, so here are a few. Note that the quality of sounds you find in these varies.

Open Game Art has sounds you can download. It also offers other assets like sprites and textures.

Freesound is very well known archive of sounds. I think you need to create an account to be able to download sounds here. In a similar vein, you have Sound Bible.

The Free Music Archive also has a bunch of songs in many genres that can be downloaded. Not all of them can be used though. But they have a Creative Commons filter that lets you find clips you can use.

And the Internet Archive also has a good collection of public domain sound clips. These include speaches and historical recordings, not just sound effects. Look for the audio tag.

There are tons of other sites for sound effects. Just search for the right keywords.