Loading...
Loading...
Use this skill when working with tilemaps in Phaser 4. Covers loading Tiled JSON maps, creating tilemap layers, tile collision, dynamic tiles, tile properties, and tilemap camera culling. Triggers on: Tilemap, Tiled, tilemap layer, tile collision, tile properties.
npx skill4agent add phaserjs/phaser tilemapsPhaser Tilemaps render tile-based levels from Tiled JSON, CSV, or raw 2D arrays. Aholds parsed map data and provides methods to add tilesets, create layers, set collision, and query tiles. Layers (TilemaporTilemapLayer) are the Game Objects that actually render tiles. Phaser supports orthogonal, isometric, hexagonal, and staggered maps.TilemapGPULayer
src/tilemaps/Tilemap.jssrc/tilemaps/TilemapLayer.jssrc/tilemaps/TilemapGPULayer.jssrc/tilemaps/TilemapLayerBase.jssrc/tilemaps/Tile.jssrc/tilemaps/Tileset.jssrc/tilemaps/TilemapFactory.jssrc/tilemaps/components/src/tilemaps/parsers/tiled/class GameScene extends Phaser.Scene {
preload() {
// Load the Tiled JSON and the tileset image
this.load.tilemapTiledJSON('map', 'assets/level1.json');
this.load.image('tiles', 'assets/tilesheet.png');
}
create() {
// Create the tilemap from cached JSON
const map = this.add.tilemap('map');
// Link the tileset image to the tileset name used in Tiled
const tileset = map.addTilesetImage('tilesheet', 'tiles');
// Create a layer - layerID must match the layer name in Tiled
const ground = map.createLayer('Ground', tileset);
// Enable collision on specific tile indexes
ground.setCollision([1, 2, 3]);
}
}TilemapTilemapLayerTilemapGPULayerconst map = this.add.tilemap('map'); // Data container (not rendered)
const layer = map.createLayer('Ground', tileset); // Game Object (rendered)this.add.tilemap(key)GameObjectFactoryParseToTilemapTilemapTilesetsrc/tilemaps/Tileset.jsfirstgid// tilesetName: the name in Tiled's tileset panel
// key: the Phaser texture key (defaults to tilesetName if omitted)
const tileset = map.addTilesetImage('tilesetName', 'textureKey');
// Override tile dimensions, margin, and spacing if needed
const tileset = map.addTilesetImage('name', 'key', 16, 16, 1, 2);addTilesetImage(tilesetName, key, tileWidth, tileHeight, tileMargin, tileSpacing, gid, tileOffset)Tilesrc/tilemaps/Tile.jsindexxypixelXpixelYwidthheightpropertiescollideLeftcollideRightcollideUpcollideDownfaceLeftfaceRightfaceTopfaceBottomcollisionCallbacktint0xfffffftintModeTintModes.MULTIPLYrotationphysicsalphavisibleflipXflipYTilemapGPULayerTilemapLayer// Pass gpu: true as the 5th argument to createLayer
const layer = map.createLayer('Ground', tileset, 0, 0, true);generateLayerDataTexture()// If you edit tiles on a GPU layer, regenerate the data texture:
gpuLayer.putTileAt(5, 10, 10);
gpuLayer.generateLayerDataTexture();TilemapLayerTilemapGPULayerTilemapLayerBasesrc/tilemaps/TilemapLayerBase.jsGameObjectpreload() {
this.load.tilemapTiledJSON('map', 'assets/map.json');
this.load.image('tiles', 'assets/tileset.png');
}
create() {
const map = this.add.tilemap('map');
const tileset = map.addTilesetImage('TilesetNameInTiled', 'tiles');
const layer = map.createLayer('LayerNameInTiled', tileset);
}layerIDcreateLayer'ParentGroup/Layer'const map = this.add.tilemap('map');
const tileset = map.addTilesetImage('terrain', 'terrain-img');
const background = map.createLayer('Background', tileset);
const ground = map.createLayer('Ground', tileset);
const foreground = map.createLayer('Foreground', tileset);
// Layers are rendered in creation order. Use depth for finer control:
foreground.setDepth(10);const tiles1 = map.addTilesetImage('terrain', 'terrain-img');
const tiles2 = map.addTilesetImage('objects', 'objects-img');
const layer = map.createLayer('Ground', [tiles1, tiles2]);const map = this.add.tilemap('map');
const tileset = map.addTilesetImage('terrain', 'terrain-img');
// createBlankLayer(name, tileset, x, y, width, height, tileWidth, tileHeight)
const layer = map.createBlankLayer('dynamic', tileset, 0, 0, 50, 50, 32, 32);
// Fill it with tiles
layer.fill(1); // Fill entire layer with tile index 1
layer.putTileAt(5, 10, 10); // Place tile index 5 at tile coord (10, 10)// By specific tile indexes
layer.setCollision([1, 2, 3]);
// By range (inclusive)
layer.setCollisionBetween(1, 50);
// By tile property (set in Tiled's tileset editor)
layer.setCollisionByProperty({ collides: true });
// Supports arrays: { type: ['stone', 'lava'] }
// By exclusion - collide on ALL tiles except these
layer.setCollisionByExclusion([-1, 0]); // -1 is empty, 0 is often background
// From Tiled collision editor shapes
layer.setCollisionFromCollisionGroup();TilemapLayerBaseTilemaplayerTilemapmap.setLayer('Ground');
map.setCollision([1, 2, 3]); // Applies to current layer
// Or specify a layer explicitly:
map.setCollision([1, 2, 3], true, true, 'Ground');// Enable collisions between a sprite and a tilemap layer
this.physics.add.collider(player, groundLayer);
// With a callback
this.physics.add.collider(player, groundLayer, (sprite, tile) => {
if (tile.index === 5) {
// Hit a special tile
}
});
// Overlap detection instead of collision
this.physics.add.overlap(player, groundLayer, (sprite, tile) => {
// Player is overlapping this tile
});setCollision*collisionCategorycollisionMask// Access tile properties
const tile = layer.getTileAt(10, 5);
console.log(tile.properties.damage); // Custom property from Tiled
console.log(tile.properties.type); // Custom property from Tiled
// Set collision based on custom properties
layer.setCollisionByProperty({ collides: true });
layer.setCollisionByProperty({ type: ['wall', 'rock'] });// Callback by tile index - fires when physics body overlaps these tiles
map.setTileIndexCallback([5, 6, 7], (sprite, tile) => {
// Called for tiles with index 5, 6, or 7
console.log('Hit tile', tile.index, 'at', tile.x, tile.y);
}, this);
// Callback by tile location - fires for tiles in a rectangular area
map.setTileLocationCallback(10, 10, 5, 5, (sprite, tile) => {
// Called for any tile in the 5x5 region starting at (10, 10)
}, this);
// Per-tile callback
const tile = layer.getTileAt(10, 5);
tile.collisionCallback = (sprite, tile) => {
// Custom logic for this specific tile
};const tile = layer.getTileAt(10, 5); // By tile coords (or null)
const tile = layer.getTileAt(10, 5, true); // nonNull: Tile with index -1 instead of null
const tile = layer.getTileAtWorldXY(worldX, worldY); // By world coords
const exists = layer.hasTileAt(10, 5); // Boolean check
// Region queries
const tiles = layer.getTilesWithin(0, 0, 10, 10); // Tile coord region
const tiles = layer.getTilesWithinWorldXY(x, y, w, h); // World coord region
const tiles = layer.getTilesWithinShape(circle); // Shape overlap
// Functional queries
const water = layer.filterTiles(t => t.properties.type === 'water');
const spawn = layer.findTile(t => t.properties.isSpawn);
layer.forEachTile(t => { /* iterate all tiles */ });layer.putTileAt(5, 10, 10); // Place tile index 5 at (10, 10)
layer.putTileAtWorldXY(5, worldX, worldY); // Place by world coords
layer.putTilesAt([[1, 2], [3, 4]], 10, 10); // Place a 2x2 grid
layer.removeTileAt(10, 10); // Remove tile
layer.fill(1, 0, 0, 10, 10); // Fill 10x10 region with index 1
layer.replaceByIndex(5, 10); // Replace all index-5 with index-10
layer.copy(0, 0, 5, 5, 20, 20); // Copy 5x5 from (0,0) to (20,20)
layer.randomize(0, 0, 10, 10, [1, 2, 3, 4]); // Random tiles in region
layer.weightedRandomize([{ index: 1, weight: 4 }, { index: 2, weight: 1 }], 0, 0, 10, 10);
layer.shuffle(0, 0, 10, 10); // Shuffle tiles in regionconst tileXY = layer.worldToTileXY(worldX, worldY); // World -> tile coords
const worldXY = layer.tileToWorldXY(tileX, tileY); // Tile -> world coords
// Reuse a vector to avoid allocation
const vec = new Phaser.Math.Vector2();
layer.worldToTileXY(worldX, worldY, true, vec); // snapToFloor = truecreateFromObjectsTilemap// Create sprites from all objects on the 'Enemies' object layer
const enemies = map.createFromObjects('Enemies', {
gid: 26, // Match by tile GID
classType: Enemy // Custom class extending Sprite
});
// Match by name
const coins = map.createFromObjects('Items', {
name: 'coin',
key: 'coin-texture',
frame: 0
});
// Match by type
const spawns = map.createFromObjects('Spawns', {
type: 'player-spawn'
});
// Access raw object layer data
const objectLayer = map.getObjectLayer('Enemies');
objectLayer.objects.forEach(obj => {
console.log(obj.name, obj.x, obj.y, obj.properties);
});createFromObjects(layerName, config, useTileset)idgidnametypeclassTypeSpritescenecontainerkeyframeignoreTilesetTilemapLayerTilemapGPULayerTilemapLayerBaseElapseTimerpreUpdate// Isometric map
const map = this.add.tilemap('iso-map');
const tileset = map.addTilesetImage('iso-tiles', 'iso-img');
const layer = map.createLayer('Ground', tileset);
// Get tile at world coords in isometric space
const tile = layer.getIsoTileAtWorldXY(worldX, worldY);
// TilemapGPULayer does NOT support iso/hex/staggered - use TilemapLayerorientation| Method | Description |
|---|---|
| Link tileset name to texture |
| Create layer ( |
| Create empty layer for procedural maps |
| Convert Tiled objects to Sprites |
| Get raw object layer data |
| Set current active layer for shorthand methods |
TilemaplayerTilemapLayerBasesetCollision(indexes)setCollisionBetween(start, stop)setCollisionByProperty(props)setCollisionByExclusion(indexes)setCollisionFromCollisionGroup()setTileIndexCallback(indexes, cb, ctx)setTileLocationCallback(x, y, w, h, cb, ctx)getTileAt(x, y, nonNull)getTileAtWorldXY(wx, wy, nonNull, cam)getTilesWithin(x, y, w, h, opts)getTilesWithinWorldXY(wx, wy, w, h, opts, cam)getTilesWithinShape(shape, opts, cam)hasTileAt(x, y)hasTileAtWorldXY(wx, wy, cam)filterTiles(cb)findTile(cb)forEachTile(cb)putTileAt(tile, x, y)putTileAtWorldXY(tile, wx, wy)putTilesAt(arr, x, y)removeTileAt(x, y)fill(index, x, y, w, h)copy(sx, sy, w, h, dx, dy)randomize(x, y, w, h, indexes)weightedRandomize(weights, x, y, w, h)shuffle(x, y, w, h)swapByIndex(a, b)replaceByIndex(find, replace)createFromTiles(indexes, replacements, config)worldToTileXY(wx, wy, snap, vec, cam)tileToWorldXY(tx, ty, vec, cam)| Method | Description |
|---|---|
| Regenerate GPU texture after tile edits |
indexxypixelXpixelYwidthheightpropertiescollideLeftRightUpDowncollisionCallbacktintrotationalphaflipXflipYphysicsaddTilesetImagenullcreateLayer'GroupName/LayerName'createLayernullsetCollisionthis.physics.add.collider()putTileAtgenerateLayerDataTexture()nullnonNull: trueindex === -1insertNullinsertNull: truenullsetTileIndexCallbacksetTileLocationCallbackxycreateLayer| File | Purpose |
|---|---|
| Main data container with all map-level methods |
| Registers |
| Shared base for CPU and GPU layers (extends GameObject) |
| CPU-rendered layer (multi-tileset, all orientations) |
| GPU-accelerated layer (v4, WebGL, orthographic, single tileset) |
| Individual tile data (index, position, collision, properties) |
| Tileset data (name, firstgid, dimensions, image) |
| Pure functions: |
| Tiled JSON parsers: |
| Orchestrates parsing and Tilemap creation |
| Layer data structure |