Your First PhaserJS Game

Background Music and Sound Effects

Enhance your PhaserJS game by adding background music and sound effects for a more immersive player experience.

In the last chapter, we added a Score and Health System to give our game some extra flavor. Now, let’s crank up the vibe by adding background music and some juicy sound effects! 🎸 Trust me, a little background music and sound can totally level up the player’s experience, making every jump and collision feel way more real.


Step 1: Download and Prepare the Sound Files 🎼

First, grab the sound files from this link: link and extract the contents into the assets folder in your project. We’ll use these for background music and different sound effects like collecting items or getting hurt by spikes.


Step 2: Preload the Sound Files in loadingScene.js 🎛️

Open up loadingScene.js and add the following code to preload the sound files in the preload function:

// load sounds
this.load.audio("bgm", "assets/sounds/bgm.mp3");
this.load.audio("collect", "assets/sounds/collect.mp3");
this.load.audio("hurt", "assets/sounds/hurt.mp3");

Explanation 🔍

These lines load the background music and sound effects into Phaser so they’re ready to use. Each sound file is given a unique identifier (e.g., "bgm", "collect", "hurt") that we’ll use when calling them in the game.


Step 3: Initialize and Play the Background Music 🎵

Now, let’s make that music play! Head over to mainScene.js and, at the start of the create function, add the following code:

if (!this.bgm_sound && !this.hurt_sound && !this.collect_sound) {
    this.hurt_sound = this.sound.add("hurt");
    this.collect_sound = this.sound.add("collect");
    this.bgm_sound = this.sound.add("bgm");
}
this.bgm_sound.play({ loop: true, volume: 0.5 });

What’s Happening? 🧠

  • If Condition: This block prevents the sounds from re-initializing if the game restarts, which could otherwise lead to duplicate sounds.
  • Sound Additions: this.sound.add(...) loads the sounds we preloaded into usable Phaser audio objects.
  • Play Music: this.bgm_sound.play(...) starts the background music. We set { loop: true, volume: 0.5 } to make the music continuous and set a balanced volume.

Step 4: Playing Sound Effects on Events 🎯

Now let’s add sound effects for when the player collects apples and gets hurt by spikes! These sounds make each action feel much more impactful. 🎸

  1. Hurt Sound: Add this code to the overlap callback inside the addSpikes function.

    if (!this.hurt_sound.isPlaying) {
        this.hurt_sound.play();
    }
  2. Collect Sound: Similarly, add this code to the overlap callback inside addCollectables.

    if (!this.collect_sound.isPlaying) {
        this.collect_sound.play();
    }

Explanation 🔊

  • Checking if Sound is Playing: The isPlaying check ensures that the sound only plays once per collision, rather than triggering multiple times in a single overlap.
  • Playing the Sound: If the sound isn’t already playing, it plays, enhancing the player’s experience with immediate feedback for collecting or taking damage.

Congratulations! 🎉

You’ve successfully leveled up your game with background music and sound effects! 🎸 Now every apple collected and every spike hit will feel alive with sound.


Complete Code 📜

If you missed anything or made some accidental changes, here’s the complete code for reference! 💻🔧


import Phaser from "phaser";
 
export default class LoadingScene extends Phaser.Scene {
    constructor() {
        super({
            key: "LoadingScene"
        });
    }
    preload() {
        // background
        this.load.image("bg", "assets/bg.png")
 
        // ground
        this.load.image("ground", "assets/ground.png")
 
        // spike
        this.load.image("spike", "assets/spike.png")
 
        // items
        this.load.spritesheet("apple", "assets/Items/Apple.png", {
            frameWidth: 32,
            frameHeight: 32
        })
        this.load.spritesheet("collected", "assets/Items/Collected.png", {
            frameWidth: 32,
            frameHeight: 32
        })
 
        // main character
        this.load.spritesheet("player_idle", "assets/character/idle.png", {
            frameWidth: 32,
            frameHeight: 32
        })
        this.load.spritesheet("player_hit", "assets/character/hit.png", {
            frameWidth: 32,
            frameHeight: 32
        })
        this.load.spritesheet("player_jump", "assets/character/jump.png", {
            frameWidth: 32,
            frameHeight: 32
        })
        this.load.spritesheet("player_run", "assets/character/run.png", {
            frameWidth: 32,
            frameHeight: 32
        })
 
        // platforms
        this.load.image("platform_brown", "assets/Platforms/Brown.png")
        this.load.image("platform_grey", "assets/Platforms/Grey.png")
 
        // falling platforms
        this.load.image("falling_platform_off", "assets/FallingPlatforms/Off.png")
        this.load.spritesheet("falling_platform_on", "assets/FallingPlatforms/On.png", {
            frameWidth: 32,
            frameHeight: 10
        })
 
        // Trampoline
        this.load.image("trampoline_idle", "assets/Trampoline/Idle.png")
        this.load.spritesheet("trampoline_jump", "assets/Trampoline/Jump.png", {
            frameWidth: 28,
            frameHeight: 28
        })
 
        // load sounds
        this.load.audio("bgm", "assets/sounds/bgm.mp3")
        this.load.audio("collect", "assets/sounds/collect.mp3")
        this.load.audio("hurt", "assets/sounds/hurt.mp3")
    }
    create() {
        // main character animations
        this.anims.create({
            key: "player_idle_anim",
            frames: this.anims.generateFrameNumbers("player_idle", {
                start: 0,
                end: 10
            }),
            frameRate: 20,
            repeat: -1
        })
        this.anims.create({
            key: "player_hit_anim",
            frames: this.anims.generateFrameNumbers("player_hit", {
                start: 0,
                end: 6
            }),
            frameRate: 12,
        })
        this.anims.create({
            key: "player_jump_anim",
            frames: this.anims.generateFrameNumbers("player_jump", {
                start: 0,
                end: 0
            })
        })
        this.anims.create({
            key: "player_run_anim",
            frames: this.anims.generateFrameNumbers("player_run", {
                start: 0,
                end: 11
            }),
            frameRate: 20,
            repeat: -1
        })
 
        // falling platform on
        this.anims.create({
            key: "falling_platform_on_anim",
            frames: this.anims.generateFrameNumbers("falling_platform_on", {
                start: 0,
                end: 3
            }),
            frameRate: 12,
            repeat: -1
        })
 
        // apple animation
        this.anims.create({
            key: "apple_anim",
            frames: this.anims.generateFrameNumbers("apple", {
                start: 0,
                end: 16
            }),
            frameRate: 20,
            repeat: -1
        })
 
        // Trampoline Jump Animation
        this.anims.create({
            key: "trampoline_jump_anim",
            frames: this.anims.generateFrameNumbers("trampoline_jump", {
                start: 0,
                end: 7
            }),
            frameRate: 20,
            repeat: 0
        })
 
        this.scene.start("MainScene");
    }
    update() {
 
    }
}

Now you have everything! 🚀 Enjoy creating your awesome PhaserJS game!