phaser tutorial top-down games with Tiled

HTML5 Phaser Tutorial – Top-Down Games with Tiled

I’m a huge fan of top-down 2D games, mainly RPG’s, adventure games and dungeon crawlers.

In this tutorial we’ll create a basic template you can use to make your own top-down games using Phaser, an awesome HTML5 game framework.

This template will be expanded in further tutorials to add the ability to move between levels, work on mobile and more cool stuff. If there are aspects you’d like me to cover in future tutorials feel free to post that on the comments!

We’ll be using a free map editor called Tiled to create our level. One nice thing about Phaser is that you can easily load map files exported from Tiled (JSON format).

This tutorial builds on top of the concepts covered in our previous Phaser tutorial, so if you are not familiar with States, preloading assets and rendering sprites you might want to check that tut first.

Learn Phaser by building 15 games

If you want to master Phaser and learn how to publish Phaser games as native games for iOS and Android feel free to check Zenva‘s online course The Complete Mobile Game Development Course – Build 15 Games.

Source code files

You can grab them from here (updated to version 2.4.2). If you want us to notify you when we release new tutorials on Phaser or HTML5 game development don’t forget to click “subscribe to our list” when downloading the files (if you choose not to you won’t hear from us!).

Tutorial goals

1-Learn to create levels for your game using Tiled and load them using Phaser.

2-Learn how to create a basic top-down game starter.

Concepts covered

-Setting the game size in pixels
-Tiled basic usage
-Tile layers and object layers
-Creating sprites from object layers
-Moving a character in a top-down level

Tutorial requirements

-This tutorial builds on the concepts covered in our previous Phaser tutorial HTML5 Phaser Tutorial – SpaceHipster, a Space Exploration Game, so it assumes you know how to setup a game, work with States, preload game assets and create sprites.

-Basic to intermediate knowledge of JavaScript. If you need a refreshment feel free to check our JavaScript beginners video course at Zenva Academy.

-A code editor or IDE. My personal preference at the moment is Sublime Text.

-Get Tiled, an Open Source and free level editor.

-Grab Phaser from it’s Github repo. You can either clone the repo or download the ZIP file.

-You need to run the code and Phaser examples using a web server. Some popular options are Apache (WAMP if in Windows, MAMP if in Mac). Some lightweight alternatives are Mongoose web server and Python’s HTTP server. Take a look at this guide for more details.

-Download the full tutorial source code and game assets here. If you want us to let you know when we release new tutorials on Phaser or HTML5 game development don’t forget to subscribe to our list!

-Have the documentation and the examples page at hand. Also don’t forget that you can always find answers by looking at the source code of Phaser itself!

Get Tiled-Face

Tiled is a really awesome level editor created by Thorbjørn Lindeijer which allows you to visually create tile-based levels for your games. The main file format these levels use is TMX. In order to use these levels in Phaser we need to export them as JSON.

When I talk about “tiles” and “tiled-based games” what I mean are games where the levels are composed of individual small blocks or pieces. Check out the Wikipedia definition if you are not 100% familiar with this concept.

To create a new map in Tiled go to File -> New:

tiled tutorial create new map

On width and height specify the number of tiles your level will have on each dimension. Tile size refers to the size of the individual tiles. Make sure Orientation is set to “Orthogonal” and Layer format to “CSV”.

The next step is to create the Layers. A level will have different layers that sit on top of each other. The naming of the layers is important here as we need to refer to that in the code later on.

There are two types of layers:

-Tile layer: layer made of tiles/blocks.
-Objects layer: layer where you create vector objects that can contain metadata.

You can create layers using the “+” button under layers, to rename them just click on the name of the newly created layers. The order matters, you can rearrange them using the arrows.

tiled create layers

In our example we’ll have two tile layers: one for the background called backgroundLayer (doesn’t collide with the player) and one for the blocking elements called blockedLayer (walls, trees, etc). We’ll also have one objects layer (objectsLayer) that will represent game elements, in this case the player starting location in the level, the collectables/items, a door (which we’ll extend in a future tutorial). In this layer you’d want to add enemies and more stuff. This is all just a suggestion and how I normally do it, it is by no means a convention or a rule of the framework.

Loading the tileset

A tileset is a set of individual tiles, which come in an image. You can have many tilesets on your tilemaps. We’ll use just one: assets/images/tiles.png.

To load a tileset: Map -> New Tileset

tiled add tileset

The nice retro tileset we’ll use is from Open Game Art and it’s a public domain image (CC0), so you can use it for both non-commercial and commercial projects.

The tiles are 16×16 and there is no separation between them or margin. The “name” in the text field, keep that name in your head as we need to refere to it when joining the tileset with the map in Phaser.

Create the level

You can now create your level. Now it’s really up to you. What I did was fill the backgroundLayer with a black tile (using the bucket tool), then changed to the blockedTile and painted some walls and trees:

tiled simple level

The object layer

We’ll add 3 different types of objects or game elements: items that will be collected by the player, the player starting position, and a door that will take you to a new level (to be implemented in a follow-up tutorial).

These objects will be represented by sprites from the tileset, but that is just for OUR simplicity. Phaser will show the sprite you tell it to when creating a Sprite object.

To insert new objects: select the objectsLayer layer, click on the Insert Tile button (the one that shows a picture of the sunset) then click on the tile you want to show, then click on the location of the object within the map.

tiled create object

We’ll add some blue and green teacups, a door and a “player”:

tiled map level

Adding properties to the objects

How is Phaser going to know what these elements represent and what sprite should be used to display them? Lets add that as object properties.

Click on the “Select object” button from the menu, then double click on any object and you’ll see a dialog where you can enter properties.

Enter a property called “type” with value “item” to the tea cups (this is not the “type” select dropdown!, this is within the Properties area), “playerStart” for the player location and “door” to the door.

For the blue cups enter a property “sprite” with value “bluecup”, “greencup” for the green cup, “browndoor” to the door. None to the player start as it won’t represent a sprite, but a location for us to use. These values are the sprite keys we’ll implement in Phaser for the corresponding image assets (peak at /assets/images).

**You can also just create one of each element, then select the element with the right click and click “duplicate”, this will allow you to quickly replicate an object and then drag it to it’s final position.

We won’t implement the door behavior in this tutorial, but enter these properties so you can guess where I’m going with this:

door properties

Before we move any further, I’d like to make it clear that this will work with the game template we are building in this tutorial, it is not a default Phaser functionality. Phaser only provides the ability to create several sprites from objects using the same sprite key. Take a look at the Tilemap documentation to learn what Phaser provides in this aspect.

Once you are doing export the level as a JSON file. File -> Export As -> Json Files, save into /assets/tilemaps.

Hola Mundo Phaser

I’ll go through this section without stepping into much details as these concepts were covered in the previous Phaser tutorial.

In this game we’ll have three states: Boot, Preload and Game. You can always add a main menu screen as we did in the previous tutorial.

Let’s start by creating index.html, where we’ll include the game files:

I prefer using the non-minified version of Phaser when doing development (phaser.js) as it makes it easier to debug errors. When working with HTML5 game development libraries it’s good practice to constantly refer to the source code itself to find answers. Not everything can be found on StackOverflow and getting familiar with the framework’s code itself can save you hours.

main.js creates the game itself and defines the game size in pixels, which I’ve set to a very small size for this example. The reason being, the tileset I’ll be using is also small and I wanted to have the game not showing the entire level (which is not that big) in the browser space.

By creating all the game objects inside a parent object called TopDownGame (this is what’s called the namespace pattern) we don’t pollute the global scope with our game elements. This is good practice as it could happen that you are including some other libraries in your project and their names match those of the objects you are creating so then you have a conflict!. Whereas if you put everything inside TopDownGame there won’t be any conflicts, unless another library created an object called TopDownGame in the global scope which is unlikely.

(Btw this:

basically means that if TopDownGame exists, then use it, if it doesn’t exist then initiate it as an empty object)


In Boot.js we’ll create the Boot state, where we load the images for the loading screen (just a loading bar in this example) and define other game-level configurations.

Since we are using Phaser.ScaleManager.SHOW_ALL the game will show as large as it can to fit the browser space, but it wont’ show more than 160×160 pixels of the game world, as that’s the limit we defined in main.js.


Preload.js will contain the loading of the assets, including the loading of the tilemap. See how the tileset iteself is simply loaded as another sprite. It will be later on when we relate the tilemap level with the tileset:


The following code in the create() method will show the map (without the objects) on your browser:

The first thing we did was create a Tilemap object from the loaded JSON file. What’s a map without the images? we need to add the tileset image to this map, which we do with'tiles', 'gameTiles');, where “tiles” is the name we gave the tileset in Tiled, and “gameTiles” is the image key as defined in Preload.js (I made those two different in purpose to make it more clear what they are referring to).

Then we load the layers, and make the blockedLayer “collision enabled”. The number between 1 and 2000 is an index range for the tiles for which we want to enable collision (in this case such a big number should include them all which is what I intended). In order to obtain this number open level1.json and in “layers” – “data” of the two layers find the largest number you can find, in this case 1896 so I put 2000 just to be sure I didn’t miss a slightly larger number. So in theory, you could just use one single layer, and define certain tiles as collision-enabled by specifying their index range.

WARNING: A previous version of this tutorial said put 100000 instead of 2000. The problem with putting unnecessary large numbers is that you are running more loops affecting the performance of your game

I find it easier to work with one layer for the background and one for the collision elements as I don’t want to count tiles one by one, that is just my preference here.

Lastly, we make the world the same size as the map.

Finding objects by type

Remember that “type” properties we gave to the objects in the level? Well I’d like to be able to find the objects of a certain type, so we’ll build a utility method in Game.js for that.

Tilemap objects have a “objects” property which is an array with the objects of each layer (you could have many object layers!). We’ll use this method to find the objects that have the property “type” of the value we want. I recommend you take a look at the file /src/Tilemap.js from the downloaded Phaser library and to the Tilemap documentation. You can also just use this method but it’s always better to understand where it came from.

When calling this method, it will give us an array of objects as they are represented in the assets/tilemaps/level1.json file.

Create sprites from Tiled objects

We are able to find tiled objects by type, and now we’d like to create sprites for them. This method in Game.js will help us out. This will become more clear over the next section where we create the tea cups.

We are copying all the properties you might have entered in Tiled. For example for the door we entered a bunch of properties. Well, this will all be copied to the sprite. Even if you entered sprite properties such as “alpha” (for transparency), this will be moved along to the sprite you are creating here.

** We are not using Tilemap.createFromObjects here because I wanted to be able to specify the type and the sprite inside of Tiled. If createFromObjects is what you need for your game I recommend you use that!

I love tea

Let’s create the tea cups! they’ll be rendered after this:


Adding the door will follow the same approach:


But we can’t move around yet and find it.

The player

We are representing the player start position with an object of type “playerStart”. What we’ll do is find that object, then create the player sprite on that location and set the camera to focus on the player, and activate cursor keys to move the player with the arrows (to be implemented shortly):

Player movement

Listen to the cursor keys and adjust the player velocity accordingly. We’ll do this in the update() method:

Now you can move your player around! but there is no collision yet.


Add the following to update(). This works in the same way as we covered in the previous tutorial, but see how you can also just put in a layer, as we are doing with this.blockedLayer:

Implementing collect():

And enterDoor(), which is something left for a follow-up tutorial:

And that’s it!

We can now create a level in Tiled, load it in Phaser and move around a character around with the cursor keys!

phaser tutorial top-down games with Tiled

Feel free to use this code for your own games, and it’s always nice if you link back to us 🙂

If you haven’t already, you can download this tutorial game files and assets here.

Where to go next?

You can check our online course HTML5 Mobile Game Development with Phaser for a comprehensive training on this awesome framework, created by professional game developer Codevinsky.

HTML5 Game Development with Phaser

These other courses on HTML5 game development and JavaScript that might be of your interest as well!

Also, feel free to share your thoughts in the comments and let us know what else you’d like us to write about!

Published by

Pablo Farias Navarro

Pablo is an educator, developer and entrepreneur. Founder of Zenva, Pablo has published over 30 online courses that teach game, app and web development. Pablo has also created educational content for companies such as Amazon and Intel.

Share this article

Leave a Reply

54 Comments on "HTML5 Phaser Tutorial – Top-Down Games with Tiled"

Sort by:   newest | oldest | most voted
Greg Malone

I appreciate the effort you’ve made here — a really important topic. Unfortunately, the tutorial falls apart at the “Adding properties to objects” section — you rushed it and it refers to views and features not evident in Tiled editor (perhaps the Mac version is different than the version you use?). So, frustrated, I’ll go learn Tiled directly from Tiled, and then come back to your tutorial to see if I can figure out what you meant. Perhaps you could clean it up a bit? Thanks again for the great effort.


Good tutorial , work fine with phaser !

just a question about this line:
//collision on blockedLayer, 100000, true, ‘blockedLayer’);

why using 100000 ?, in the json file “level1.json” the max value for the blockedLayer is 1896 , we can do :, 1896, true, ‘blockedLayer’);

doing 100000 , may this affect performance ( FPS) ?


John A Durston


Thanks for posting these tutorials.

I have one small problem with this one though – I downloaded the source and ran the game, but only the objects move with the camera, the collision layer image doesn’t move (its collision does however).

I tried to edit the code but didn’t really get very far. Any ideas?


Hi there, the problem you are having is due to a tileset/webgl bug in version 2.1.3. It would seem the tileset doesn’t update after the first render due to a subtle change in Pixi. Try using an older version of Phaser or try using the 2.2 dev version (which fixes the issue) which you can get from here:


I had this problem too. Try to apply the phaser.js script. Download it from the other page and try to apply.


I can verify that downloading the latest version (2.2.1) works great.

@pablo is there a place to share the fixes to git back with you? I assume you don’t want us posting this code on github. (if you did, you would have done that in the first place rather than email download)

Greg Malone

Coming back to this tutorial and having issues getting objects to show up in the map until I realized that for each object tile in the tileset that you intend to use, you have to (per this tutorial) separately load and tag each object tile w/ the key name — in addition to loading the tileset that already contains the textures.

Doesn’t Tiled/Phaser provide a more direct way to know which texture to use in the tileset without having to redundantly load and tag each of them individually, in addition to loading the tileset?



Hi, thanks for this tutorial it is very good.
Can you tell when will be the next? 🙂

Marcio Andrey Oliveira

Amazing tutorial.

I’m hoping for more 🙂


Cool tutorial, thank you Pablo!
I have a question about Preload.js. Why do we need to cut out cups, player and the door from tiles.png and make separate images? Why don’t you use just one image tiles.png?


great tutorial. But I can’t download the source code or the resources, I click on the link, insert my email but I get no link to download from. Yes, I checked my SPAM folder. 🙁

Adinan Alves

Nice tutorial! Helped me a lot!

Now, about the door action, when will you post the follow up showing how to enter another level?

Matt Hughson

With the supplied code, the camera does not work properly. The objects scroll as the camera moves, but the backgroundlayer does not. Any idea what is going wrong here?

Matt Hughson

I am on Phaser version 2.4.2.

Matt Hughson

I am sure. I just cloned it a couple days ago, and can see 2.4.2 in the release notes. I did find that it works in CANVAS mode, but not in AUTO (or webGL).

Alam Katon

when i choose tiles on tileset for create blocked layer, some tiles not work for collision. you know what?

Victor Marx

Hello. The link ( ) to download the file is broken. Could you correct it?

Vita O

but how do i do level2, level3 …. without using xxx states? i got for each level seperate .csv file. How do i index them?

Josh Kersting

had an issue with the findObjectsByType function returning an empty array.

for anyone else having a similar issue I found that instead of “if( === type)” I just needed “if(element.type === type)”

Benjamin Groeneveld

You should make your screenshot even smaller!! Thankfully you can modify the url in a separate window..

After reading the churn around the 10000 to 2000 for the collision enabled block layer value I wrote out a little function for my gulp build step that takes a path value, parses the JSON data and pulls back the highest length of items in the data array. This is a small part of code taken from a larger implementation, obviously, but the gist is that I put a replaceable comment in my src/config.js and during my build step I figure out the highest value needed and replace the comment with this value. I also gather some other useful information… Read more »