Monday, July 20, 2015

Phaser Tilemap

I was out of town all weekend for my daughter's soccer tournament, but I found 15 minutes to spend trying out tile maps in Phaser.

The ground in my frog soccer game is just green, set by the game.stage.backgroundColor field. It would be nice to have some grass or soccer field lines on it. Sure, I could make some images and set them on the screen manually just like the other sprites, but a tile map would be easier.

Phaser makes it very simple, as long as you are using Tiled for a map editor. I just had to remember what I named my layer and tileset when I changed the code.

In Tiled, I created a single layer with a single tileset. I named the layer groundLayer and I named the tileset groundTiles. The tileset was create from a texture sheet I made a while ago using TexturePacker.

Name the Layer something meaningful - and remember it!

The Tileset name and image have to match what you use with Phaser!

After saving my tile map in Tiled's JSON format as ground.json, I updated my game code. In the preload phase I added two lines of code, one to load the tile map itself and one to load the image with all the tiles in it. This is the same image I used to create the tileset in Tiled.

function preload() {

    game.load.image('tree2', 'images/tree2.png');
    game.load.image('frog', 'images/frog.png');
    game.load.spritesheet('ball', 'images/ball_animation.png', 45, 45);

    game.load.tilemap('map', 'images/ground.json',
            null, Phaser.Tilemap.TILED_JSON);
    game.load.image('tiles', 'images/groundTiles.png');

}

I once again added a few more variables, map and layer. Then in the create phase, it only took four lines of code to get myself grounded.

var map;
var layer;

function create() {

    game.stage.backgroundColor = "0x409d5a";

    map = game.add.tilemap('map');
    map.addTilesetImage('groundTiles', 'tiles');;
    layer = map.createLayer('groundLayer');
    layer.resizeWorld();

    group = game.add.group();

    // ... other stuff ...

}

The call to game.add.tilemap("map") on line 8 creates a map object that represents the whole map exported from Tiled. In this case, since there is only one layer, there's not all that much to it. Immediately after creating the map, I had to call addTilesetImage (line 9) to add the image created in preload to the map and associate it with the tileset in the file. Since my tileset was named groundTiles in Tiled, I associate that with the "tiles" image - which was the same one I used to create the groundTiles tileset. Making these match is important!

The next step is to create the layer I want. Again, my simple map had only one layer named groundLayer. After creating the layer object on line 10, I can conveniently use it to resize the world to match the layer dimensions.

One note here...I don't create the group object that holds all my other sprites until after the map/layer thing is done. If I create the group object first, event if I don't add any sprites to it yet, everything that is added to it will draw under the ground tiles. Took me a few minutes to catch that mistake the first time.

Alright, that's all for today. I know it's not much but I did actually put this thing in an open repo on GitHub if you want to look at the full source code. Also, remember to check the comic for today.

Amphibian.com comic for 20 July 2015