This is a series of blog posts about creating modular worlds with tilemaps in the Phaser 3 game engine. If you haven’t, check out the first post where we used static tilemaps to create a Pokémon-style game world. In this post, we’ll dive into dynamic tilemaps and create a puzzle-y platformer where you can draw platforms to help get around obstacles:

Final example that we’ll create

The next post covers creating a procedural dungeon world, and the one after that will cover integrating Matter.js to create a wall-jumping platformer.

Before we dive in, all the source code and assets that go along with this post can be found in this repository. These tutorials use the latest version of Phaser (v3.16.2) and Tiled (v1.2.2) as of 02/26/19. Some pairings of older versions of Phaser and Tiled don’t get along well, so I recommend using these two version.

Intended Audience

This post will make the most sense if you have some experience with JavaScript (classes, arrow functions & modules), Phaser and the Tiled map editor. If you don’t, you might want to start at the beginning of the series, or continue reading and keep Google, the Phaser tutorial and the Phaser examples & documentation handy.

Alright, Let’s get into it!

The Tilemap API

Before we build the platformer, let’s start with a bird’s-eye view of the tilemap API. We talked about the following bits last time:

In this post, we’ll dive into two new pieces of the API:

A Tilemap isn't a display object. It holds data about the map and can contain one or more layers, which are the display objects that actually render Tile objects. They come in two flavors: StaticTilemapLayer & DynamicTilemapLayer . A StaticTilemapLayer is fast, but the tiles in that layer can’t be modified and can’t render per-tile effects like flipping or tint. A DynamicTilemapLayer trades some speed for the flexibility and power of manipulating individual tiles.

Static and dynamic layers share much of the same API. They both have methods for checking whether a tile exists (e.g. hasTileAt ). They both have methods for getting access to tiles in the map ( getTileAt , findTile , forEachTile , etc.). Dynamic layers have a set of additional methods for adding, removing, randomizing, etc. tiles within the layer (e.g. putTileAt , removeTileAt , randomize , etc.).

The tilemap API is flexible, so you can choose the right tool for the job. You can mix static and dynamic layers together in the same map. You can also convert a dynamic layer into a static layer, allowing you to generate a level on the fly and then optimize it.

Painting Tiles

For the first example, we’ll load up a level made with Tiled and then paint & erase tiles on the fly. We couldn’t use static layers here, so we’ll need to reach for dynamic layers.

Tileset by 0x72 under CC-0, https://0x72.itch.io/16x16-industrial-tileset

We set up dynamic layers in the same way as static layers, except using map.createDynamicLayer instead of map.createStaticLayer :

Once you’ve got a dynamic layer loaded up, you can start manipulating tiles using the DynamicTilemapLayer API:

The tilemap layer (and tilemap) methods that get or manipulate tiles often come in pairs. One method — like putTileAt - will operate on tile grid units, e.g. (0, 2) would correspond to the first column and third row of the layer. The other method - like putTileAtWorldXY - will operate in world pixel units, making it easier to do things like find which tile is under the mouse. There are also methods for converting from tile grid units to world pixel coordinates and vice versa: worldToTileXY , tileToWorldXY .

Putting these methods together with Phaser input, we can draw tiles in a layer with the mouse:

The following example puts all of this together and allows you to paint tiles by clicking and erase tiles by clicking while holding shift. worldToTileXY & tileToWorldXY are used to create a simple graphic overlay to visualize which tile the mouse is currently over.

Note: you’ll want to click on the “Edit on CodeSandbox” button and check out the code in full screen where you can see all the files easily.