Showing posts with label jumping. Show all posts
Showing posts with label jumping. Show all posts

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

Wednesday, November 11, 2015

Tuning the Jumps in my Phaser Platformer

I found just a few minutes to work on my 8-bit-style Phaser platformer since the weekend. Just about everyone in my family is sick in some way, including myself. So with my limited time I decided to fine-tune the jumps.

In my really basic code so far, a jump was accomplished by hitting space on the keyboard. If the frog was on the ground while space was pressed, the frog's y-velocity was set to a constant number. This worked fine, but it resulted in every jump being the same height. Tapping the spacebar for a millisecond caused the same jump as holding down the key for ten seconds. Well, actually holding down the key caused the frog to jump over and over and over again. I wanted to fix that too.

I was looking for a way to make a longer keypress result in more height, up to a limit. After reading a few ideas tossed out there by other people on the Internet, I decided on what to do. Here is part of my new update function, with the enhanced jump logic (remember, you can find the complete source code on GitHub):

var jumpTimer = 0;

function update() {

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

    if (spacebar.isDown) {
        if (frog.body.onFloor() && jumpTimer === 0) {
            // jump is allowed to start
            jumpTimer = 1;
            frog.body.velocity.y = -400;
        } 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 ...

}

Here's how it works... I've introduced a new variable, jumpTimer, which will keep track of how long the jump lasts. If the spacebar is not being pressed, jumpTimer is always set to 0. No jumping is taking place. But when the spacebar is being pressed, some other stuff happens.

First, I check to see if the frog is on the floor of something and jumpTimer is 0. Obviously, I only want a jump to start if the frog is on the ground. But the other part of that ensures that a new jump can start only if jumpTimer has been reset - and it won't be reset until the player releases the space key. This prevents the endless bouncing when holding down the button. Anyway, if both of those conditions are met, jumpTimer is set to 1 and the frog's y-velocity is set to -400. Why -400? I just liked that value after playing around with it. You might want a different value.

In the other case, jumpTimer is greater than 0 but less than 31, the jump is continuing. Each time in here, jumpTimer is incremented. This happens once per frame, so this function keeps the frog moving up for a maximum of 30 frames. After that, no more velocity will be added and gravity pulls the frog back to the ground. I reduce the amount of velocity added by the value of jumpTimer times 7 in order to slow down the vertical rise the longer the button is held down. This looked slightly more natural. Again, I chose 7 just by playing around with it until I found a number I liked.

Animation of the new jump tests.

I'm happy with how it turned out. Next I think I'll try to add an enemy or something and work on the attack mechanics. While you wait for me to write about that, read today's comic. It's almost time to start thinking about Christmas shopping. Maybe it's already that time. Depends on how much of a procrastinator you are.

Amphibian.com comic for 11 November 2015