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 で使われるのは基本的にはマップファイルとタイルセットファイルそれからタイルセットの画像ファイルのようです。
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 の例を見るとタイルのサイズとオフセットの関係は下の図のようになっているようです。
かなり分かりにくいですがマスやタイルの順番は左上原点になっているのに オフセットの座標計算については左下原点となっているようでした。
関連すると思われる 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 からテクスチャ座標を取得できるようにしておく
- 描画するマス座標とテクスチャ座標、オフセットから頂点バッファを作る
- 三角形にテクスチャを貼り付けるシェーダで描画する