« Back to Blog

Phaser Platformer Series: 2 ‘Game feel’ and Inertia

posted on 14 March 2021

There’s a quality in games that makes them fun to play often referred to as ‘game feel’ or ‘juicing’. This can be things like nice sound effects, responsive controls, recoil when firing a gun – essentially it’s attention to detail, and little extras that add to the richness of a game. There are lots of youtube videos explaining it and in-depth talks on the subject.

When it comes to game feel in platformers, this blog post by Brendan Vance sums it up perfectly. The gist is, a nice feeling platformer comes down to ‘sticky friction’, more commonly know as inertia. Super Mario is the textbook example of this. Mario accelerates from standing, he slows down gradually and you feel the weight of him as he jumps.

In our previous tutorial, pressing left and right moved our square by setting the bodies x value. That obviously works, but we can jazz it up a bit and use some simple physics to give the controls that nice weightiness and ‘feel’ that we are after.

Instead of just adjusting our hero’s x coordinate, we can use arcade physics properties to make our hero accelerate and slow down. It just so happens that Niklas Berg has created a fantastic phaser platform boilerpate. It’s a fairly complete project, with ES6, webpack, and all sorts of goodies. If you’re a bit more advanced in your javascript skills, then it’s well worth checking out. We’re keeping things simple and starting nice and slow with these tutorials, so I’m going to borrow some of his ideas and use them in our more stripped-back example.

This is what we’ll be making:

See the Pen
Phaser Platformer: 2 ‘Game feel’ and inertia
by Digitherium (@digitherium)
on CodePen.


The first thing we want to do is set a top speed for our hero so they don’t just keep getting faster and faster:

player.body.maxVelocity.x = 200;
player.body.maxVelocity.y = 500;

You’ll notice there is an x (for going left and right) and y (up and down or jumping) value. Now we can make our hero accelerate as an arrow key is pressed, so they can gradually speed up. With our top speed set they’ll max out at a certain point and just keep cruising:

var standing = player.body.blocked.down || player.body.touching.down;
//if left key is down then move left
if (cursors.left.isDown) {
    //if hero is on ground then use full acceleration
    if (standing) {
        player.setAccelerationX(-acceleration);
    }
    //if hero is in the air then accelerate slower
    else {
        player.setAccelerationX(-acceleration / 3);
    }
}

We are also going to treat our heroes acceleration differently based on whether they are standing on the ground or in the air jumping. If your feet are on the floor it’s easy to pick up speed and break into a run. Pretty much impossible if you are in the air! Using phasers arcade physics we can tell if a body is colliding using ‘blocked’ and ‘touching’. I believe blocked is for moving bodies and touching is for still ones. By checking for either we know whether there is ground beneath the player’s feet and that they are standing.

If our hero is on the ground, then we will set their acceleration using our acceleration variable. If they are in the air jumping then accelerate much slower (a third of the speed).

If neither arrow key is down, then our hero should be slowing down:

player.setAccelerationX(((player.body.velocity.x > 0) ? -1 : 1) * acceleration / 3);

Here we use the conditional operator to work out whether our hero is going left or right (negative or minus number). Left would be a minus acceleration and right a positive one. Based on that we can slow down the character by adjusting their acceleration in the other direction, the aim be to get their velocity back to 0. This is being called in the update loop remember, so each time it’s called the hero’s velocity will be decreasing or increasing and hopefully gettings towards 0, which would be standing still.

There is a slight problem with this code, in that it’s very hard to actually hit zero perfectly. So everytime that line of code runs, unless our heros’ velocity is exactly 0, it will end up adding either left or right acceleration. The result of this is that as our hero gets close to standing still, they seem to vibrate and freak out a little bit and never actually stand still completely still. Not good. To stop this we can just say:

if (Math.abs(player.body.velocity.x) < 10 && Math.abs(player.body.velocity.x) > -10) 
{
  player.setVelocityX(0);
  player.setAccelerationX(0);
}

Which loosely translates to; if our hero is close to a stand still, just stop them moving completely straight away. i.e there is a threshold below which we don’t want to bother gradually slowing down, we just want to stop immediately. We put this in the code first and that whole section looks like this:

 //if hero is close to having no velocity either left or right then set velocity to 0. This stops jerky back and forth as the hero comes to a halt. i.e. as we slow hero down, below a certain point we just stop them moving altogether as it looks smoother
if (Math.abs(player.body.velocity.x) < 10 && Math.abs(player.body.velocity.x) > -10) {
    player.setVelocityX(0);
    player.setAccelerationX(0);
}
//if our hero isn't moving left or right then slow them down 
else {
    //this velocity.x check just works out whether we are setting a positive (going right) or negative (going left) number  
    player.setAccelerationX(((player.body.velocity.x > 0) ? -1 : 1) * acceleration / 3);
}

Nice. Our hero now speeds up and slows down and generally feels a lot nicer. Next up, let’s improve the jumping.

view all the code on codepen
download the source on github.