用途
Tilemaps 是 Phaser 4 中用于渲染基于瓦片关卡的技能。它从 Tiled JSON、CSV 或原始二维数组读取地图数据,将解析后的地图数据保存为 Tilemap,并通过图层(TilemapLayer 或 TilemapGPULayer)实际渲染瓦片。适用于平台跳跃、俯视角、等距、六边形等各类瓦片地图游戏场景。
主要能力
- 加载 Tiled JSON 地图与图集图片,创建 tilemap 与图层。
- 支持正交、等距、六边形和交错地图。
- 瓦片碰撞设置:按索引、按范围、按属性、按排除、按 Tiled 碰撞编辑器形状。
- 瓦片查询:按瓦片坐标、世界坐标、区域、形状查询,以及 filterTiles、findTile、forEachTile 等函数式查询。
- 运行时修改瓦片:放置、移除、填充、复制、随机化、加权随机化、洗牌、替换、交换等。
- 坐标转换:世界坐标与瓦片坐标互转。
- 对象图层:通过 createFromObjects 将 Tiled 对象转换为 Sprite。
- 瓦片动画:自动解析 Tiled 中定义的瓦片动画。
- Arcade 物理集成:collider 与 overlap 检测,支持瓦片回调。
- TilemapGPULayer:WebGL 专用的高性能图层,将整个图层作为单个四边形用着色器渲染。
使用方式
基本流程为:加载 JSON 与图集图片、创建 tilemap、添加 tileset 图片、创建图层、设置碰撞。
class GameScene extends Phaser.Scene {
preload() {
this.load.tilemapTiledJSON('map', 'assets/level1.json');
this.load.image('tiles', 'assets/tilesheet.png');
}
create() {
const map = this.add.tilemap('map');
const tileset = map.addTilesetImage('tilesheet', 'tiles');
const ground = map.createLayer('Ground', tileset);
ground.setCollision([1, 2, 3]);
}
}
创建 GPU 图层时,向 createLayer 传入第 5 个参数 gpu: true:
const layer = map.createLayer('Ground', tileset, 0, 0, true);
创建空白图层用于程序化地图:
const layer = map.createBlankLayer('dynamic', tileset, 0, 0, 50, 50, 32, 32);
layer.fill(1);
layer.putTileAt(5, 10, 10);
碰撞设置示例:
layer.setCollision([1, 2, 3]);
layer.setCollisionBetween(1, 50);
layer.setCollisionByProperty({ collides: true });
layer.setCollisionByExclusion([-1, 0]);
layer.setCollisionFromCollisionGroup();
物理集成示例:
this.physics.add.collider(player, groundLayer);
this.physics.add.collider(player, groundLayer, (sprite, tile) => {
if (tile.index === 5) { /* ... */ }
});
this.physics.add.overlap(player, groundLayer, (sprite, tile) => { /* ... */ });
瓦片查询示例:
const tile = layer.getTileAt(10, 5);
const tile = layer.getTileAtWorldXY(worldX, worldY);
const exists = layer.hasTileAt(10, 5);
const tiles = layer.getTilesWithin(0, 0, 10, 10);
const water = layer.filterTiles(t => t.properties.type === 'water');
运行时修改瓦片示例:
layer.putTileAt(5, 10, 10);
layer.removeTileAt(10, 10);
layer.fill(1, 0, 0, 10, 10);
layer.replaceByIndex(5, 10);
layer.randomize(0, 0, 10, 10, [1, 2, 3, 4]);
layer.weightedRandomize([{ index: 1, weight: 4 }, { index: 2, weight: 1 }], 0, 0, 10, 10);
对象图层示例:
const enemies = map.createFromObjects('Enemies', {
gid: 26,
classType: Enemy
});
const objectLayer = map.getObjectLayer('Enemies');
适用场景
- 使用 Tiled 编辑的瓦片地图关卡。
- 需要瓦片碰撞与 Arcade 物理交互的平台游戏或俯视角游戏。
- 需要运行时动态修改瓦片(如破坏地形、随机生成)的场景。
- 需要高性能渲染大量瓦片的 WebGL 项目(TilemapGPULayer)。
- 等距、六边形、交错地图项目。
限制
- Phaser Tiled 解析器不支持“Collection of Images”图集,每个 tileset 的所有瓦片必须位于单张图集图片中。
- TilemapGPULayer 仅支持单一 tileset、仅支持正交地图(不支持等距/六边形/交错)、仅支持 WebGL 渲染器(无 Canvas 回退)。
- TilemapGPULayer 最大地图尺寸为 4096x4096 瓦片,最大唯一瓦片 ID 为 2^23(8,388,608)。
- TilemapGPULayer 修改瓦片后不会自动显示,需调用 generateLayerDataTexture() 重新生成数据纹理。
- 每个图层只能创建一次,重复调用 createLayer 会返回 null 并警告。
- tileset 名称与图层名称必须与 Tiled 中完全一致,否则返回 null 并输出控制台警告。
- 必须调用 setCollision 系列方法后物理碰撞才会生效。
- 瓦片回调需要物理 collider/overlap 处于激活状态。
关键源文件路径
src/tilemaps/Tilemap.js、src/tilemaps/TilemapLayer.js、src/tilemaps/TilemapGPULayer.js、src/tilemaps/TilemapLayerBase.js、src/tilemaps/Tile.js、src/tilemaps/Tileset.js、src/tilemaps/TilemapFactory.js、src/tilemaps/components/、src/tilemaps/parsers/tiled/