Wednesday, December 23, 2015

Adding More Stages to my Phaser Platformer

Last week I started getting my platformer set up to have more than just one stage. I created some State objects, one for the title screen and one for the sandbox stage. Today I wanted to continue that process by adding a second playable stage.

Let's call this new stage Stage 1. I think I'm going to number the stages by the bit positions, so we'll have Stage 1 (1), Stage 2 (10), Stage 4 (100), etc. For now, I'm going to leave the sandbox stage in there as Stage 0.

Because of the groundwork I laid over this past weekend, adding the additional stage was easy. If you remember, I created a playingState function which returned a Phaser State object representing the playable stage. Today, I modified that function and renamed it to stage. It now takes a single numeric argument and uses that to select which map and music will be loaded.

Here is a simplified example of my code:

function stage(n) {

    var thisLevel = n;

    // ... other variable declarations

    function preload() {
        this.load.pack("main", "assets/pack.json");
    }

    function create() {

        // load the map for thisLevel
        map = this.add.tilemap("stage" + thisLevel);

        // load the music for thisLevel
        bgmusic = this.sound.add("bgmusic" + thisLevel);

        // ... all the other stuff ...

    }

    // ... all the other functions ...

    return {
        preload: preload,
        create: create,
        update: update
    };

}

For the above code to work as expected, I had to add more game assets to my pack.json file. I now have two tilesets with keys stage0 and stage1, and two audio types with keys bgmusic0 and bgmusic1. Adding more stages is as simple as adding more tilesets and music to the asset pack.

In the game setup, I simply call stage twice. The first time to create the State object for the sandbox and the second time to create the State object for stage 1.

var stageSelectState = selectStage();

var sandboxStage = stage(0);
var stageOne     = stage(1);

var game = new Phaser.Game(width, height, Phaser.CANVAS, "gameArea",
  stageSelectState);

game.state.add("sandbox", sandboxStage);
game.state.add("one", stageOne);

While this works and was fairly simple, it bothers me a little bit. Since 99% of the stage is exactly the same (the only behavior that differs based on the input parameter is in the create function) I really hate calling the stage function more than once, each time creating a functionally identical closure. I think I'm going to optimize this a little more. Stay tuned.

As I've mentioned before, you can play the in-progress game at https://amphibian.com/eight-bit and you can check out the complete source code on GitHub. Leave a comment with any feedback, and don't forget to read today's comic. It's part 4 of my Christmas story and includes the third and final goat!

Amphibian.com comic for 23 December 2015