Tiled フォーマットの覚え書き

Tiled

ゲームを作る時に使ってみたいと思って前に Tiled について調べたことについて書いて置きます。

Tiled はアクションゲームや RPG などのマップをタイルで構成するためのツールです。

Tiled Map Editor | A flexible level editor

ゲームのマップ数が少ない場合はマップごとに一枚の画像を使うことも可能だと思いますが データ量を抑えたり、マップを動的に生成したりなどする場合は Tiled のようにタイルに分割して描画することになると思います。

ソースも公開されていて、色々な言語でのライブラリも作られていて利用しやすそうです。

GitHub - bjorn/tiled: A flexible level editor

Libraries and Frameworks — Tiled 1.1.0 documentation

フォーマット

Tiled で使われるのは基本的にはマップファイルとタイルセットファイルそれからタイルセットの画像ファイルのようです。

JSONXML のフォーマットがあります。

JSON Map Format — Tiled 1.1.0 documentation

TMX Map Format — Tiled 1.1.0 documentation

マップファイルとタイルセットファイルは普通分けて使われるようです。

ソースコードにいくつか例が含まれていました。

tiled/examples at master · bjorn/tiled · GitHub

例は XML のものしか無いんですが、これを読み込んで JSON にエクスポートすることもできました。 JSON の方が慣れているので使うときは JSON 使おうかと考えています。

tiled/examples/perspective_walls.tmx を JSON エクスポートすると下のようになりました。 (長いため一部省略しています)

{"height":32,
 "infinite":false,
 "layers":[
        {
         "data":[0, 0, 0, 0, 0...],
         "height":32,
         "name":"Walls",
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":32,
         "x":0,
         "y":0
        }],
 "nextobjectid":1,
 "orientation":"orthogonal",
 "renderorder":"right-down",
 "tiledversion":"1.1.5",
 "tileheight":31,
 "tilesets":[
        {
         "firstgid":1,
         "source":"perspective_walls.tsx"
        }],
 "tilewidth":31,
 "type":"map",
 "version":1,
 "width":32
}

タイルセットは下のようになりました。

{"columns":4,
 "image":"perspective_walls.png",
 "imageheight":256,
 "imagewidth":256,
 "margin":0,
 "name":"perspective_walls",
 "spacing":0,
 "tilecount":16,
 "tileheight":64,
 "tileoffset":
    {
     "x":-32,
     "y":0
    },
 "tileproperties":
    {
     "13":
        {
         "door":"true"
        },
     "14":
        {
         "door":"true"
        },
     "15":
        {
         "pickup":"true"
        }
    },
 "tilepropertytypes":
    {
     "13":
        {
         "door":"string"
        },
     "14":
        {
         "door":"string"
        },
     "15":
        {
         "pickup":"string"
        }
    },
 "tilewidth":64,
 "type":"tileset"
}

Map

http://doc.mapeditor.org/en/stable/reference/json-map-format/#map

Map はゲームのマップでどのようにタイルを配置するか、それからマップのサイズなどが定義されています。

Tile Layer

http://doc.mapeditor.org/en/stable/reference/json-map-format/#layer

Tile Layer はマップ中のタイル配置です。 data のフィールドで GID で各マスに配置するタイルを指定します。 data のマスは行優先順 (raw-major order) で左上から順番になっています。 GID は tileset の firstgid を使ってタイルセット中の各タイル定義に固有に振られた global id になります。 GID が0は何もないという意味になるようです。 タイルセットを複数使う場合は GID が被らないように firstgid 指定する必要があると思います。

perspective_walls の例を見るとタイルのサイズとオフセットの関係は下の図のようになっているようです。

f:id:tkaaad97:20180708201252p:plain

かなり分かりにくいですがマスやタイルの順番は左上原点になっているのに オフセットの座標計算については左下原点となっているようでした。

関連すると思われる issue がありました。

Tile object Y coordinate not saved properly · Issue #386 · bjorn/tiled · GitHub

Object Layer

Tile Layer の他に Object Layer というのもあるようです。 これはおそらく描画には関係ないデータで床や壁の当たり判定やリスポーン位置などの定義に使われるのではないかと思います。

Tileset

Tileset は各タイルの定義で画像のサイズやオフセットなどです。 Tileset に使う画像は全て同じサイズで、行優先順 (row-major order) で並べる想定になっています。

Tiled の描画方法

ライブラリが色々な言語で作られていて利用できる場合もありますが、パーサーしかなかったり描画は自前で書く場合もあると思います。 基本的にはタイルの画像がそれぞれのマスに描画できればいいのでそんなに難しくは無いと思います。

OpenGL では下のような流れでの描画になると思います。

  • タイルセット画像を読み込みテクスチャを作成する
  • GID からテクスチャ座標を取得できるようにしておく
  • 描画するマス座標とテクスチャ座標、オフセットから頂点バッファを作る
  • 三角形にテクスチャを貼り付けるシェーダで描画する