Friday, November 13, 2015

Hit the Ground? Play a Sound!

I didn't get to add any enemies to my Phaser 8-bit style platformer this week, but I did add some sound effects. Even though I hadn't used background music before in a game before, it was very easy to add. Playing a sound when the frog jumps was also simple.

But what about playing a sound when the frog lands back on the ground? Not as easy.

First, the simple sounds. For background music, I used "Ouroboros" by Kevin MacLeod (http://incompetech.com). The jump and landing sounds were public domain from FreeSound.org. I added them all to my asset pack file. I gave the background music the key bgmusic1, the jump sound the key jump, and the landing sound the key thud.

In the create function I made the sound objects.

function create() {

    // ... other create stuff ...

    bgmusic = game.sound.add("bgmusic1");
    bgmusic.volume = 0.3;
    bgmusic.loop = true;
    bgmusic.play();

    jumpSound = game.sound.add("jump");
    thudSound = game.sound.add("thud");

}

I start playing the background music right away, after setting it to loop and lowering the volume. I don't like the background music so loud that you can't hear the other sound effects. In Phaser, volume is set with a number between 0 (not audible) and 1 (full volume).

What do I do with the jump and thud sounds? Jump is easy.

function update() {

    // ... other stuff ...

    if (spacebar.isDown) {
        if (frog.body.onFloor() && jumpTimer === 0) {
            // jump is allowed to start
            jumpTimer = 1;
            frog.body.velocity.y = -400;
            jumpSound.play();
        } else if (jumpTimer > 0 && jumpTimer < 31) {
            // keep jumping higher
            jumpTimer++;
            frog.body.velocity.y = -400 + (jumpTimer * 7);
        }
    } else {
        // jump button not being pressed, reset jump timer
        jumpTimer = 0;
    }

    // ... other stuff

}

In the jump function I made on Wednesday, I simply add a call to jumpSound.play() there on line 10 when a jump starts. Couldn't be easier. Now for the hard part...

Playing a sound when the frog collides with the ground seemed obvious at first - just call thudSound.play() in the optional collision function. The collide function lets you specify an optional function that is called when the sprites being checked actually hit each other. But this is not a good place to play a thud sound. The reason is that the frog and the ground are in collision for every frame in which the frog is sitting on the ground. The sound will play all the time, except when the frog is in the air because of a jump or a fall. Not exactly what I wanted.

function update() {

    game.physics.arcade.collide(frog, layer, function(f, t) {
        // -------------------------------------------
        // don't do this!
        // the sound plays almost all the time!
        // -------------------------------------------
        thudSound.play();
    });

    // ... other stuff ...    

}

The trick is to set a flag when the frog is falling - that is, when the y-velocity is greater than 0. This could happen because he jumped or because he walked off a ledge. In either case, gravity pulls him down and the game engine sets the y-velocity to a value greater than 0. When this happens, I set a falling flag on the frog object. Then, I check to see if the frog's physics body is on the floor and the falling flag is true. If these two cases are both met, it means that the frog just hit the ground after a fall. It's there that I call thudSound.play() and reset the falling flag to false. That was some alliteration.

function update() {

    game.physics.arcade.collide(frog, layer);

    if (frog.body.onFloor() && frog.falling) {
        frog.falling = false;
        thudSound.play();
    }

    // ... other stuff ...    

    if (frog.body.velocity.y > 0) {
        frog.falling = true;
    }
    
}

Now whenever the frog hits the ground, a thud sound is heard just once. I'm happy with these results and you'll be happy with today's comic. And remember, you can get the full source code of this game on GitHub! Okay, now for the comic:

Amphibian.com comic for 13 November 2015