Platform Game Tutorial: "Ride on" Platforms

By Richard Davey on 23rd January 2015   @photonstorm

Welcome!

One of the biggest genres of game that devs new to Phaser want to create are platformers. It appears they can't get enough of their Mario fix. Being a fan of the genre myself I figured it would make a great new series, especially when you factor in all the things that a platform game needs. In this issue we'll get started with the platforms themselves.

Get the source

There are two source files this week. The first shows the core mechanics of just the platforms working and the second is the game Jump Up!

I'm only going to highlight the most important parts of the code here. So please always look at the source first. If you've questions about something I didn't cover then ask on the forum.

Run / Edit Part 1 on jsbin or codepen. Run / Edit Part 2 on jsbin or codepen. Or clone the phaser-coding-tips git repo.

"Ride on" Platforms

What does a platform game need? Platforms of course! In this weeks Coding Tips we're going to create two different types of platform, each with their own characteristics. First up is our standard platform. It looks like this:

Platform

The platforms are added to a Physics Group:

this.platforms = this.add.physicsGroup();

this.platforms.create(0, 64, 'ice-platform');
this.platforms.create(200, 180, 'platform');
this.platforms.create(400, 296, 'ice-platform');
this.platforms.create(600, 412, 'platform');

this.platforms.setAll('body.allowGravity', false);
this.platforms.setAll('body.immovable', true);
this.platforms.setAll('body.velocity.x', 100);

This simply creates 4 platforms, stops gravity from making them fall and gives them all the same initial horizontal velocity.

When the player jumps on this type of platform we let Phaser handle the collision. Due to the way Arcade Physics works there is a special condition that means that the player will automatically "ride" with the platform. So as it moves horizontally the players x position is adjusted to match.

You can see this by running Part 1 of the code and jumping on to a green platform.

"Slippery" Platforms

But what if we don't want that to happen? What if we want our player to fall off the platform, and not ride it? Perhaps the platform is covered in ice? For that we'll let the platform set its own friction.

Platform

This is done by specifying a collision callback for the platforms:

this.physics.arcade.collide(
    this.player, this.platforms, 
    this.setFriction, null, this
);

Here we are colliding the player with the platforms group. If they intersect then setFriction is called:

setFriction: function (player, platform) {

    if (platform.key === 'ice-platform')
    {
        player.body.x -= platform.body.x - platform.body.prev.x;
    }

},

The conditional checks if the platform is an ice one, and if so adjusts the players body to compensate for the distance the platform has travelled.

Obviously you don't have to check the image key to do this - it would make more sense if you had a special custom Game Object that knew if it was slippery or not, but the end result is the same. You need to effectively undo the horizontal drag that was applied by Arcade Physics.

If you run the code you'll see that on the green platforms you can ride them, but on the snow covered ones you slip right off. Perfect.

Jump Up!

Now we've got two types of platform, let's create a little game from them.

In this game you will just have to try and jump to the top of the world. The game world is 2000 pixels tall and you start at the bottom, so you've a bunch of platforms to traverse. All of them are moving at varying speeds and they alternate between 'slippery' and not.

Game

Run the second piece of code to play this game.

Hang time

One thing platform games often do is give you a small window of opportunity to still jump, even when you've fallen off the side of a platform. This is implemented in the Jump Up game through the edgeTimer property.

In the update function we keep track of the state of the player. If they were standing in the previous frame, but are no longer standing, then we know they have either jumped or fallen off the edge of a platform:

Standing is defined as being either stood on a platform, or on the bottom of the game world:

var standing = this.player.body.blocked.down || this.player.body.touching.down;

If they are no longer standing, but were in the previous frame, we give them 250ms to make a jump:

if (!standing && this.wasStanding)
{
    this.edgeTimer = this.time.time + 250;
}

The edgeTimer value is checked against the clock - and if the player presses the jump button, and they do so within 250ms of falling, they will still be allowed to perform the jump.

It's up to you what values you set for this. 250ms may be too high, or too low, it's very game specific. But it felt "right" for this particular game. Tweak it as you need.

Scrolling background

As the player gets further up the stack of platforms we wanted to make the background scroll. To reflect the height they were gaining. To do this we used a TileSprite with a vertically repeating texture. The TileSprite position was then hooked to the Game Camera in the update function:

this.sky.tilePosition.y = -(this.camera.y * 0.7);

The minus sign is added because otherwise the background scrolls in the wrong direction to the world.

The * 0.7 is there to make the background scroll slower than the camera. This gives the illusion of a bit more depth to the scrolling. Feel free to change this value - try 0.1 for a really 'distant' scroll. Or even 2.0 for a much faster (than the camera) scroll. Lots of fun to be had here :)

Brain Food

There's a lot you could do to improve the game, even while keeping the concept the same:

  • Have 2 platforms per row with more vertical space between them
  • Make the player die if they fall too far
  • Add something to collect as they jump up
  • Add a goal to reach at the top
  • Inverse the game - so they start at the top and must drop down, but not too fast

Whatever you decide to do hopefully this has given you a taster. If you evolve this further I'd love to know!

Phaser Evolution

It's worth noting that while writing this tutorial I realised that it would make far more sense if the friction of an object was a Phaser level property, not something you had to adjust via a collision callback. So I added it as a new Body property. At the time of writing this is only in the dev version of Phaser (the relevant commit is here)

However if you're now using a version of Phaser > than 2.2.2 you'll have this feature built-in. So all you need do is this when creating your objects:

var platform = this.platforms.create(x, y, 'platform');
platform.body.friction.x = 0;

By changing the Body.friction property you can influence what happens if something lands on it. The default is x: 1, y: 0 - which means the player would 'ride' the platform. If you set x to zero, it will slip off. If you set x to 0.5 it will slip-off, but at half the rate of the platforms velocity (i.e. a slippery platform, but not quite!).

You then don't need to use a collision callback at all, Phaser will handle it for you.

Until this feature lands in the master branch use the callback approach described in this issue.

Comments

comments powered by Disqus