mcpField
T
tilemaps

tilemaps

github.com/phaserjs開発40.6k989 回インストール10 週間前に更新
リポジトリ

tilemaps について

Phaser のタイルマップを読み込み、描画、検索、編集するためのスキルリファレンスです。Tiled データ、CSV、配列を使うゲーム開発者向けで、複数のマップ方向と CPU・GPU レイヤーを扱います。

主な機能

  1. 01Tiled JSON、CSV、配列のマップデータ
  2. 02タイルセットと描画レイヤー
  3. 03タイルの衝突と物理設定
  4. 04タイル検索と実行時編集
  5. 05GPU レイヤー描画

活用シーン

  1. 01Tiled マップからのレベル作成
  2. 02タイルのプロパティに基づく衝突設定
  3. 03ゲーム中のマップタイル編集
  4. 04ワールド座標からのタイル検索

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/phaserjs/phaser --skill tilemaps

インストール後、Claude Code で/tilemapsを入力して読み込まれたか確認します。

詳細

タイルマップ

Phaser のタイルマップは、Tiled JSON、CSV、または生の 2D 配列からタイルベースのレベルをレンダリングします。Tilemap は解析済みのマップデータを保持し、タイルセットの追加、レイヤーの作成、衝突判定の設定、タイルのクエリを行うメソッドを提供します。レイヤー(TilemapLayer または TilemapGPULayer)は、実際にタイルをレンダリングするゲームオブジェクトです。Phaser は直交、アイソメトリック、ヘキサゴナル、スタッガードのマップをサポートしています。

主要なソースパス: 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/ 関連スキル: ../loading-assets/SKILL.md、../sprites-and-images/SKILL.md

クイックスタート

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]);
    }
}

流れは常に次のとおりです。JSON + 画像をロードし、タイルマップを作成し、タイルセット画像を追加し、レイヤーを作成し、衝突判定を設定します。

コアコンセプト

Tilemap と Layer

Tilemap はデータコンテナであり、表示オブジェクトではありません。解析済みのマップデータ(レイヤー、タイルセット、オブジェクト)を保持し、それらを操作するメソッドを提供します。TilemapLayer または TilemapGPULayer は、ディスプレイリストに追加されてタイルをレンダリングする実際のゲームオブジェクトです。

const map = this.add.tilemap('map');    // Data container (not rendered)
const layer = map.createLayer('Ground', tileset);  // Game Object (rendered)

this.add.tilemap(key) は GameObjectFactory に登録されたファクトリです。これは ParseToTilemap に委譲され、キャッシュから読み取って Tilemap インスタンスを返します。

タイルセット

Tileset(src/tilemaps/Tileset.js)は、タイルセット名(Tiled 由来)をロード済みのテクスチャにリンクします。firstgid、タイルの寸法、マージン、スペーシングを保持します。

// 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) - タイルセット名が解析済みのマップデータにすでに存在する場合、既存の Tileset オブジェクトをテクスチャで更新します。存在しない場合(Tiled 以外のマップ)、新しい Tileset を作成します。

重要: Phaser の Tiled パーサーは「Collection of Images」タイルセットをサポートしていません。すべてのタイルは、タイルセットごとに 1 つのタイルセット画像に含まれている必要があります。

Tile クラス

レイヤー内の各セルは Tile オブジェクト(src/tilemaps/Tile.js)です。主なプロパティ:

  • index - タイルセット内のタイルインデックス(空の場合は -1)
  • x、y - タイル座標(ピクセルではなくタイル単位)
  • pixelX、pixelY - レイヤー原点からの相対ピクセル位置
  • width、height - ピクセル単位のタイルサイズ
  • properties - Tiled からのカスタムプロパティ(オブジェクト)
  • collideLeft、collideRight、collideUp、collideDown - 辺ごとの衝突フラグ
  • faceLeft、faceRight、faceTop、faceBottom - 衝突最適化のための注目面フラグ
  • collisionCallback - タイルごとの衝突コールバック関数
  • tint - ティントカラー値(デフォルト 0xffffff)
  • tintMode - ティントブレンドモード(デフォルト TintModes.MULTIPLY)
  • rotation - 回転角度
  • physics - 物理エンジン固有のデータ(例: ボディ)用のオブジェクト
  • alpha、visible、flipX、flipY - ミックスインから継承
TilemapGPULayer(v4.0.0)

TilemapGPULayer は、TilemapLayer に代わる高性能な WebGL 専用の選択肢です。シェーダーを使用してレイヤー全体を単一のクワッドとしてレンダリングするため、ほぼ完全に GPU 依存になります。

// Pass gpu: true as the 5th argument to createLayer
const layer = map.createLayer('Ground', tileset, 0, 0, true);

機能:

  • レイヤーごとに単一のタイルセットのみ(マルチタイルセット不可)
  • 最大タイルマップサイズ: 4096x4096 タイル
  • 最大ユニークタイル ID: 2^23(8,388,608)
  • タイルの反転とタイルアニメーションをサポート
  • 直交マップのみ(アイソメトリック、ヘキサゴナル、スタッガード不可)
  • LINEAR フィルタリングによる滑らかなタイル境界(シームなし)
  • NEAREST フィルタリングによるシャープなピクセル

制限:

  • レイヤーの編集は自動的に表示されません。タイルを変更した後に generateLayerDataTexture() を呼び出してください。
  • WebGL レンダラーのみ(Canvas フォールバックなし)
  • 単一のレイヤーで複数のタイルセットを使用できません
// If you edit tiles on a GPU layer, regenerate the data texture:
gpuLayer.putTileAt(5, 10, 10);
gpuLayer.generateLayerDataTexture();
TilemapLayerBase

TilemapLayer と TilemapGPULayer はどちらも TilemapLayerBase (src/tilemaps/TilemapLayerBase.js) を継承しており、これは GameObject を継承しています。基底クラスは、すべてのタイルのクエリ、操作、および衝突のメソッドを提供します。これには以下のコンポーネントミックスインが含まれます: Alpha、BlendMode、ComputedSize、Depth、ElapseTimer、Flip、GetBounds、Lighting、Mask、Origin、RenderNodes、Transform、Visible、ScrollFactor、および Arcade Physics Collision。

一般的なパターン

Tiled JSON からの作成
preload() {
    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);
}

createLayer に渡される layerID は、Tiled のレイヤー名と完全に一致している必要があります。グループレイヤーの子は、'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);

1 つのレイヤーで複数のタイルセットを使用できます (CPU レイヤーのみ):

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)
衝突の設定

Arcade Physics でタイルの衝突を有効にする方法はいくつかあります:

// 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();

TilemapLayerBase のすべての衝突メソッドは Tilemap のメソッドを反映していますが、layer パラメータを必要としません。Tilemap では、レイヤー参照を渡すか、「現在のレイヤー」を使用できます:

map.setLayer('Ground');
map.setCollision([1, 2, 3]);  // Applies to current layer
// Or specify a layer explicitly:
map.setCollision([1, 2, 3], true, true, 'Ground');
物理演算の統合 (Arcade)
// 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* メソッド経由)。レイヤー自体には、衝突フィルタリング用の collisionCategory および collisionMask プロパティがあります。

タイルのプロパティ

タイルには、Tiled のタイルセットエディタでカスタムプロパティを設定できます:

// 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 region
座標変換
const 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 = true
オブジェクトレイヤー (Tiled)

Tiled のオブジェクトレイヤーは、ポイント、矩形、およびスプライトの配置を定義します。Tilemap の createFromObjects を使用します:

// 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) の設定オプション: id、gid、name、type、classType (デフォルトは Sprite)、scene、container、key、frame、ignoreTileset。

アニメーションタイル

タイルアニメーションは Tiled のタイルセットエディタで定義され、自動的に解析されます。TilemapLayer と TilemapGPULayer の両方がアニメーションタイルをサポートしています。TilemapLayerBase は ElapseTimer を使用して preUpdate 経由でアニメーション時間を追跡します。

アイソメトリック、ヘキサゴナル、スタッガードマップ
// 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 TilemapLayer

マップの orientation プロパティは Tiled データから設定されます。座標変換関数は、orientation に基づいて自動的に選択されます。

API クイックリファレンス

Tilemap (データコンテナ - レンダリングされない)
メソッド説明
addTilesetImage(name, key, tw, th, margin, spacing, gid, offset)タイルセット名をテクスチャにリンク
createLayer(layerID, tileset, x, y, gpu)レイヤーを作成 (gpu=true で GPU レイヤー)
createBlankLayer(name, tileset, x, y, w, h, tw, th)プロシージャルマップ用の空のレイヤーを作成
createFromObjects(layerName, config, useTileset)Tiled オブジェクトをスプライトに変換
getObjectLayer(name)生のオブジェクトレイヤーデータを取得
setLayer(layer)省略メソッド用に現在のアクティブレイヤーを設定

ほとんどのタイルクエリ/衝突/操作メソッドは、Tilemap (追加の layer パラメータ付き) と TilemapLayerBase (パラメータなし) の両方に存在します。レイヤーで直接呼び出すことをお勧めします。

TilemapLayerBase(レンダリングレイヤー - CPU および GPU)

衝突判定: setCollision(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)

TilemapGPULayer(追加)
メソッド説明
generateLayerDataTexture()タイル編集後に GPU テクスチャを再生成します
タイルのプロパティ

index(数値、-1=空)、x/y(タイル座標)、pixelX/pixelY(レイヤーを基準としたピクセル位置)、width/height、properties(Tiled からのオブジェクト)、collideLeft/Right/Up/Down(真偽値)、collisionCallback(関数)、tint(数値)、rotation(数値)、alpha、flipX/flipY、physics(エンジンデータ用のオブジェクト)

注意点

  1. タイルセット名は Tiled と完全に一致させる必要があります。 addTilesetImage の最初の引数は、Phaser のテクスチャキーではなく、Tiled で定義されたタイルセット名です。一致しない場合、null が返され、コンソールに警告が表示されます。

  2. レイヤー名は Tiled と完全に一致させる必要があります。 createLayer は Tiled のレイヤー名(またはレイヤーインデックス)を受け取ります。グループレイヤーの子は 'GroupName/LayerName' というプレフィックスが付きます。

  3. 各レイヤーは一度しか作成できません。 同じレイヤー ID で createLayer を二度呼び出すと、警告とともに null が返されます。レイヤーデータは 1 つのレイヤーゲームオブジェクトにしか関連付けられません。

  4. 物理コライダーが機能する前に setCollision を呼び出す必要があります。 タイルを衝突可能としてマークしないと、this.physics.add.collider() はすべてのタイルをすり抜けます。

  5. TilemapGPULayer は直交投影のみです。 アイソメトリック、ヘクサゴナル、スタッガードのマップはサポートしていません。また、レイヤーごとに 1 つのタイルセットしかサポートしていません。

  6. TilemapGPULayer は手動でのテクスチャ再生成が必要です。 putTileAt などの編集メソッドを呼び出した後、generateLayerDataTexture() を呼び出さないと変更が反映されません。

  7. 「Collection of Images」形式のタイルセットはサポートされていません。 Tiled パーサーは、タイルセット内のすべてのタイルが単一の画像内にあることを要求します。エクスポートされた JSON に埋め込まれたタイルセットが必要です。

  8. タイルインデックス -1 は空を意味します。 多くのメソッドは、デフォルトで空のタイルに対して null を返します。代わりに index === -1 の Tile オブジェクトを取得するには、nonNull: true を渡します。

  9. タイルマップファクトリの insertNull。 タイルマップを作成する際、insertNull: true は空のタイルに対してインデックス -1 の Tile オブジェクトではなく null を格納します。大きなスパースマップのメモリを節約できますが、空のセルに動的にタイルを配置できなくなります。

  10. タイルコールバックはアクティブな物理がある場合にのみ発火します。 setTileIndexCallback と setTileLocationCallback は、ボディとレイヤーの間の物理コライダーまたはオーバーラップが必要です。

  11. レイヤーの位置と Tiled のオフセット。 createLayer で x と y を指定しない場合、それらは (0, 0) ではなく、Tiled で定義されたレイヤーオフセットがデフォルトになります。

ソースファイルマップ

ファイル目的
src/tilemaps/Tilemap.jsすべてのマップレベルのメソッドを備えたメインデータコンテナ
src/tilemaps/TilemapFactory.jsGameObjectFactory に this.add.tilemap() を登録します
src/tilemaps/TilemapLayerBase.jsCPU レイヤーと GPU レイヤーで共有される基底クラス(GameObject を継承)
src/tilemaps/TilemapLayer.jsCPU レンダリングのレイヤー(マルチタイルセット、すべての向き)
src/tilemaps/TilemapGPULayer.jsGPU アクセラレーションのレイヤー(v4、WebGL、正投影、単一タイルセット)
src/tilemaps/Tile.js個々のタイルデータ(インデックス、位置、衝突判定、プロパティ)
src/tilemaps/Tileset.jsタイルセットデータ(名前、firstgid、寸法、画像)
src/tilemaps/components/純粋関数: SetCollision、GetTileAt、PutTileAt、SetTileIndexCallback など
src/tilemaps/parsers/tiled/Tiled JSON パーサー: ParseJSONTiled、ParseTileLayers、ParseObjectLayers、ParseTilesets、BuildTilesetIndex
src/tilemaps/ParseToTilemap.jsパースと Tilemap の作成を統括します
src/tilemaps/mapdata/LayerData.jsレイヤーデータ構造

コメント