How to Use Tiled for Browser Game Level Design

Colorful letter tiles spelling 'How' on a vibrant red background, ideal for educational content.

Tiled is the open-source level editor most indie developers reach for when their game has tile-based maps. It exports to TMX (XML) or JSON, integrates cleanly with Phaser and most other browser engines, and runs on every desktop OS. This tutorial walks through how to use Tiled for browser game work: from a blank project to a working level imported into a JavaScript engine, with object layers for spawn points and collisions.

Key takeaways

  • Tiled is free, open-source, and the de facto standard tile editor for indie game development.
  • The TMX format (XML) is human-readable; JSON export is what most browser engines consume.
  • Object layers store metadata (spawn points, triggers, collisions) separately from the tile grid.
  • Phaser has first-class TMX/JSON support via the tilemap loader.
  • Tile properties let you encode collision and behavior data directly on tiles.

What Tiled is and isn’t

Tiled is a 2D map editor. You paint tiles from a tileset onto a grid; the map saves to TMX or JSON. It doesn’t render your game, doesn’t simulate physics, doesn’t handle input. It produces a structured data file your engine reads at runtime to build the level.

Tiled supports orthogonal (top-down or side-view rectangular), isometric, staggered isometric, and hexagonal maps. Terrain sets and automapping rules save real time on tile placement. The export pipeline (manual, or via the tiled --export-map command line) fits into asset build steps.

Installation

Download Tiled from its official site, mapeditor.org. It’s free and open-source on Windows, macOS, and Linux. The download page lets you pay what you want to support development, but every feature is in the free build.

Project setup

Create a folder for your game project. Inside, put:

  • A subfolder for tileset images (PNGs from Aseprite or wherever).
  • A subfolder for Tiled map files (.tmx or .tmj).
  • A subfolder for exported JSON (if your build pipeline exports separately).

Tiled stores tileset references as relative paths. Keep the directory structure stable so the map files don’t lose their references after you move them.

Creating a new map

File → New → New Map. Set:

  • Orientation: Orthogonal for most top-down or side-view games.
  • Tile size: Match your tileset. 16×16, 32×32, 64×64 are common.
  • Map size: In tiles, not pixels. 40×30 tiles at 16px each = 640×480 px map.
  • Tile layer format: CSV is human-readable; Base64 (zlib) is smaller. JSON output handles either.

Importing a tileset

Map → New Tileset. Pick your tileset PNG (e.g., the one you exported from Aseprite). Set the tile width and height to match. Tiled will slice the PNG into tiles and show them in the Tilesets panel on the right.

For a tileset with margin or spacing (some have 1-pixel borders to prevent texture bleeding), set those values in the New Tileset dialog. Get this wrong and your tiles will show partial neighbors at the edges.

Painting tiles

Select the Stamp Brush (B). Click a tile in the Tilesets panel to select it. Left-click on the map to paint; hold and drag to keep painting. Right-click (or right-drag) on the map copies existing tiles into your brush. To remove tiles, use the Eraser (E).

Other useful tools:

  • Bucket fill (F): Fills a connected region of the current tile.
  • Shape Fill (P): Paints a rectangular (or circular) area.
  • Random mode (D): Toggles painting randomly from a multi-tile selection — good for grass or rubble.
  • Terrain Brush (T): If you’ve defined a terrain set in the tileset editor, the terrain brush paints transitions automatically.

Multiple layers

Right-click in the Layers panel → Add Layer → Tile Layer. Common layer stack for a top-down game:

  • Ground: The base terrain.
  • Decoration: Static objects on top of ground (rocks, plants).
  • Above-player: Things rendered above the player sprite (tree canopies).

Each layer renders bottom-to-top in the Layers panel. The order matters for visual stacking.

Object layers

This is where Tiled gets really useful for game logic. Object layers store rectangles, ellipses, polygons, and points with custom properties — none of which are tied to the tile grid.

Common uses:

  • Spawn points: A point object named “player_spawn” with x/y coordinates.
  • Triggers: A rectangle named “level_exit” that fires an event when the player enters it.
  • Collision shapes: Polygons that mark off non-tile-aligned collision boundaries.
  • NPCs: Point objects with custom properties (npc_id, dialogue_key) the engine reads at load.

Add an object layer (Add Layer → Object Layer). Select the Rectangle tool (R) or Insert Point (I) in the toolbar. Draw or place. Each object has a Properties panel where you add custom data (name, type, custom string/int/bool properties).

Tile properties

For tile-level metadata (e.g., is this tile a wall? a slope? deadly lava?), use tile properties. Open the tileset in the tileset editor (the Edit Tileset button in the Tilesets panel), select a tile, and add a custom property in the Properties panel, like “collides” (bool) or “damage” (int).

At runtime, your engine reads each tile’s properties and uses them. Phaser’s tilemap layer exposes per-tile properties through its API.

Exporting

Save the map (File → Save) as TMX. Tiled also writes JSON if you save as .tmj or use File → Export As → JSON.

JSON is what most browser engines consume. The output structure includes:

  • Map dimensions and tile size.
  • Tilesets (with image paths, tile properties).
  • Tile layers (as flat arrays of tile IDs).
  • Object layers (as arrays of objects with properties).

If you change the map a lot, set up a CLI export step in your build pipeline.

Loading in Phaser

Phaser’s tilemap loader handles Tiled JSON natively:

// in preload
this.load.tilemapTiledJSON('level1', 'level1.json');
this.load.image('tiles', 'tileset.png');

// in create
const map = this.make.tilemap({ key: 'level1' });
const tileset = map.addTilesetImage('my_tileset', 'tiles');
const ground = map.createLayer('Ground', tileset, 0, 0);
const decoration = map.createLayer('Decoration', tileset, 0, 0);

// spawn point from object layer
const spawn = map.findObject('Objects', obj => obj.name === 'player_spawn');
this.player = this.physics.add.sprite(spawn.x, spawn.y, 'player');

// collision
ground.setCollisionByProperty({ collides: true });
this.physics.add.collider(this.player, ground);

That’s a complete top-down map loader in about fifteen lines (the player sprite has to exist before you add the collider, hence the order). The Tiled file is the level data; the engine code is the interpreter.

Loading in vanilla Canvas

Without Phaser, parse the JSON yourself. The data layer is a flat array of global tile IDs (0 means empty; with a single tileset, the first tile is 1). To render:

const TILE = 16;
for (let y = 0; y < layer.height; y++) {
  for (let x = 0; x < layer.width; x++) {
    const id = layer.data[y * layer.width + x];
    if (id === 0) continue;
    const tileIndex = id - 1;
    const sx = (tileIndex % tilesetCols) * TILE;
    const sy = Math.floor(tileIndex / tilesetCols) * TILE;
    ctx.drawImage(tilesetImg, sx, sy, TILE, TILE, x * TILE, y * TILE, TILE, TILE);
  }
}

Same idea: read the data array, draw the corresponding tile at the corresponding position. With multiple tilesets, subtract each tileset’s firstgid instead of 1, and mask off the high flip-flag bits if you use flipped tiles.

Common mistakes

Two mistakes new Tiled users hit constantly:

  • Tileset margin and spacing: If your tileset has spacing between tiles, set it in the New Tileset dialog or you’ll see misaligned tile rendering. The bug looks like every tile is shifted by one pixel.
  • Object layer name mismatch: Your engine reads object layers by name. If you rename a layer in Tiled and don’t update the engine code, the level will load but the spawn points will be missing. Match names carefully.

Tiled vs LDtk

LDtk is a newer level editor with a more modern UI and some features that work differently from Tiled (integer grid layers, auto-layer rules, built-in world layouts). It’s worth considering if you’re starting fresh.

Tiled is still the safe default because every browser engine supports its formats. LDtk has community loaders for Phaser, but the ecosystem is younger. For a tutorial-stage project, stick with Tiled; the integration friction is lower.

Resources

Tiled’s official documentation (doc.mapeditor.org) covers every feature. The Phaser documentation has dedicated examples for tilemap loading. For background on the format family, the tile-based video game entry on Wikipedia is a useful primer.

Frequently asked questions

Is Tiled free?

Yes. Tiled is open-source and free on Windows, macOS, and Linux. You can donate to support development, but there is no paid feature tier.

Does Tiled work with Phaser?

Yes, natively. Phaser’s tilemap loader accepts Tiled JSON exports directly. You don’t need a converter.

What’s the difference between TMX and JSON?

TMX is XML; JSON is JSON. They contain the same data. Browser engines prefer JSON because parsing is cheaper and you don’t need an XML library. Use JSON for browser games.

Can I use Tiled for an isometric game?

Yes. Tiled supports orthogonal, isometric, staggered isometric, and hexagonal maps. Phaser 3.50 and later can load isometric and hexagonal Tiled maps as well as orthogonal ones.

How do I version-control Tiled files?

Use the CSV tile layer format and save as TMX (XML) or TMJ (JSON). Both are text and diff cleanly in Git. Avoid Base64-compressed layers if you need readable diffs.

The takeaway

How to use Tiled for browser game level design comes down to: install Tiled, import a tileset, paint tile layers, add object layers for game logic, export to JSON, and load with Phaser or your engine of choice. The object layer is the underrated feature — it lets you encode spawn points, triggers, and collision shapes alongside the tile grid in a single file. For a tile-free browser game break while you’re learning, the Chrome Dino game uses procedural cactus placement instead.

🔌 Connect any AI assistant to dinogame.gg — we run an MCP server: https://dinogame.gg/mcp