SuperAPI AI 工具集

tilemaps

编程与开发

查看项目

更新于 10-15 15:27

技能介绍

用途

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/