CocosCreatorでTiledMapEditorのマップを表示する

# はじめに
2Dゲーム作りでは必須ともいえる、TiledMapEditor（マップエディタ）との連携方法をまとめてみました。

<font color="red">2018.11.19 追記
CocosCreator 2系におけるtsxファイルの読み込み方法を追記。</font>

<font color="red">2018.2.27 追記
mapノードの左下を原点(0, 0)とするよう追記。</font>

■動作環境
Windows10
CocosCreator 1.6.2
TiledMapEditor 1.0.3

■使用した素材
フィールドレイヤー用マップチップ(mapchip1.png)
![mapchip1.png](https://qiita-image-store.s3.amazonaws.com/0/94561/322d9a03-57f2-4dd5-d2ef-6cef175b29fd.png)
障害物レイヤー用マップチップ(mapchip2.png)
![mapchip2.png](https://qiita-image-store.s3.amazonaws.com/0/94561/25e4e267-8316-aaa4-6668-bedb66e39c9e.png)

# 今回目指す内容
ベーシックな連携方法についてはいろいろなサイトでも述べられているので、より複雑なゲームにも対応できるよう、以下を目指してみます。

* 複数のタイルセットを利用してマップを作成する
* マップは複数のレイヤーで構成する（下のレイヤーはフィールド、上のレイヤーは障害物といった感じに）
* マップにカスタムプロパティを設定する
* マップはプログラム中に動的に読み込む

# TiledMapEditorのインストール
[公式ページ](http://www.mapeditor.org/)からインストーラをダウンロードして実行します。
snapshotではなく、release版をダウンロードしましょう。
![window0.PNG](https://qiita-image-store.s3.amazonaws.com/0/94561/b678d4d8-8a31-9892-4c9d-f723cc695b29.png)


# マップの作成
## タイルセットの作成
TiledMapEditorを起動したら、「ファイル」→「New」→「新しいタイルセット」を選択し、フィールドレイヤーで使用するタイルセット（mapchip1.tsx）を作成します。
名前、画像ファイル(mapchip1.png)のパス、透過色、タイルの幅・高さを以下のように設定します。
![window1.png](https://qiita-image-store.s3.amazonaws.com/0/94561/0cfbb92a-bec0-aa75-d8d9-84e7316f038f.png)


同様に障害物レイヤーで使用するタイルセット（mapchip2.tsx）を「新しいタイルセット」で作成します。
こちらは「透過色を設定する」にチェックを入れ、スポイトで画像の左上あたりを透過色として選択します。
![window2.png](https://qiita-image-store.s3.amazonaws.com/0/94561/d5b4a13b-4ff7-ddc0-458d-eeb5628eba93.png)

## マップの作成
「ファイル」→「New」→「New Map」を選択し、サンプルとして縦と横が16タイルずつのマップを作成します。
![window3.png](https://qiita-image-store.s3.amazonaws.com/0/94561/c9d2e57a-4d0a-48af-b8dc-b932b0442063.png)

「マップ」→「タイルセットを読み込み」を選択し、先ほど作成したmapchip1.tsxとmapchip2.tsxを読み込みます。
読み込むとTiledMapEditor右下のタイルセットにmapchip1とmapchip2が表示されます。
（タイルセットが表示されていない場合は「表示」→「ビューとツールバー」→「タイルセット」を選んで表示させる）
![window3-1.PNG](https://qiita-image-store.s3.amazonaws.com/0/94561/cd7be083-76d1-0b8d-3bef-21ce292c7978.png)

TiledMapEditor右上のレイヤーにて、foregroundとbackgroundのレイヤーを作成する。
![window3-2.PNG](https://qiita-image-store.s3.amazonaws.com/0/94561/4b1f4bb0-1d6b-68d2-3212-a1c35190a32c.png)

backgroundのレイヤーを選択し、適当にフィールドを描く。
![window4.png](https://qiita-image-store.s3.amazonaws.com/0/94561/bdb1cd16-b3c6-0d03-1939-5e632945479c.png)

同様にforegroundのレイヤーを選択し、障害物を描く。
![window5.png](https://qiita-image-store.s3.amazonaws.com/0/94561/62b89c8a-c812-5cf4-66f8-1c7d7539b150.png)

作成したマップはmap.tmxのファイル名で保存します。

## カスタムプロパティの設定
ここでは、木と看板は障害物であることを示すよう、木と看板のマップチップに独自のcategoryプロパティを設定します。
（このプロパティはCocosCreatorで使用します）

TiledMapEditorにmapchip2.tsxを読み込ませ、mapchip2を編集します。
木のマップチップを選択し、カスタムプロパティの下にある「＋」を選択します。
ダイアログ上でプロパティ名をcategory、型をintとしてOKを押します。
![window6.png](https://qiita-image-store.s3.amazonaws.com/0/94561/c6abadf3-745b-3c50-ee18-20f5813a19c3.png)

カスタムプロパティにcategoryが追加されたら、値に1をセットします。
![window7.png](https://qiita-image-store.s3.amazonaws.com/0/94561/99609c80-4ce2-c7d2-977f-cf9469ff4b8f.png)

看板も同様の手順でcategory=1を設定します。

# CocosCreatorでのマップ表示

## プロジェクトの作成
CocosCreatorが起動したら新規プロジェクトを作成し、以下となるようassetsを準備します。
![window8.png](https://qiita-image-store.s3.amazonaws.com/0/94561/45ae2f46-48ac-650f-ecf8-f033e62508a5.png)

シーン：scenesフォルダを作成し、「Game」のsceneを作成する。
マップ：resourcesフォルダを作成し、以下のファイルを格納する。
　　　mapchip1.png
　　　mapchip2.png
　　　mapchip1.tsx
　　　mapchip2.tsx
　　　map.tmx
　　　※あとで動的読み込みを行うため、フォルダ名は必ず「resources」にしてください。

## mapノードの作成
Node Tree上で、Canvasノード内にmapノードを新規作成（Create Empty Nodeを選択）します。
mapノードを選択し、作成したマップと同じサイズとなるよう、Size W:768 H:768と設定します。
![window9.png](https://qiita-image-store.s3.amazonaws.com/0/94561/60ff4686-28df-a06d-2d90-771b5047c5b0.png)

<font color="red">2018.2.27 追記
今後プレイヤー等のオブジェクトをmapノードに配置する場合、mapノードの左下を原点(0, 0)にしておくと配置しやすくなります。
mapノードの原点を左下に設定するには、Anchor X:0 Y:0と設定します。
またmapノードが画面の中央に表示されるよう、Position X:-384 Y:-384と設定します。</font>
![anchor3.png](https://qiita-image-store.s3.amazonaws.com/0/94561/9a102e24-b310-8de8-b951-f41fd71b0f0a.png)


## スクリプト作成とmapノードへの関連付け
assetsの中にscriptsフォルダを作成し、JavaScriptを作成します。
スクリプトの名前は「Map」に変更します。

mapノードを選択し、右側のPropertiesにある「Add Component」を押し、「Add Custom Component」→「Map」を選択します。
以下のように、mapノードにMapスクリプトが関連付けられます。
![window11.png](https://qiita-image-store.s3.amazonaws.com/0/94561/3651f70f-dae7-9ac7-a28b-5322d37f73aa.png)

## スクリプトの編集
Map.jsを以下の内容に書き換えます。

```JavaScript:Map.js
/* global cc */
cc.Class({
    extends: cc.Component,

    // use this for initialization
    onLoad: function () {
        this.loadMap();
    },
    
    //
    // Mapを読み込む
    //
    loadMap: function () {
        var self = this;
        cc.loader.load(cc.url.raw("resources/mapchip1.tsx"), function (err, result) {
            cc.loader.load(cc.url.raw("resources/mapchip2.tsx"), function (err, result) {
                cc.loader.loadRes("map", function (err, map) {
                    var component = self.node.addComponent(cc.TiledMap);
                    component.tmxAsset = map;
                    
                    // マップ読み込み完了後、看板の座標のcategoryプロパティ値を出力
                    cc.log("category: ", self.getCategory(6, 7));
                });
            });
        });
    },
    
    //
    // 指定した座標のcategory値を返す
    //
    getCategory: function (x, y) {
        var layer = this.node.getComponent(cc.TiledMap).getLayer("foreground");
        var gid = layer.getTileGIDAt(cc.p(x, y));
        var properties = this.node.getComponent(cc.TiledMap).getPropertiesForGID(gid);
        
        if (properties === undefined || typeof properties == "number") return 0;
        return properties.category;
    },
});

```

スクリプトの説明：

* 起動時にloadMap()関数を呼び、２つのタイルセットとマップのファイル名を指定して動的に読み込む（俗にいうCallback地獄になってる^^;）
* 読み込みが完了したら、看板の座標（ここではx=6, y=7）のcategoryプロパティ値をcc.log()で出力
* getCategory()関数では、以下の手順でcategoryプロパティ値を取得
  * マップのforegroundレイヤーオブジェクトを参照し、getTileGIDAt()関数でgid（タイル番号）を取得
  * getPropertiesForGID()関数でマップからプロパティ群を取得
  * プロパティ群がNullでなければ、categoryプロパティを参照

<font color="red">CocosCreator 2系はtsxファイルの読み込み方法が変更となったため、cc.loader.loadを実行している箇所は以下に読み替えてください。</font>

```
        cc.loader.loadRes("mapchip1", function (err, tsx) {
            cc.loader.loadRes("mapchip2", function (err, tsx) {
```

実行すると、ブラウザ画面上に以下のようにマップが表示されるはずです。
![window10.png](https://qiita-image-store.s3.amazonaws.com/0/94561/c1cfd572-907b-58bf-0640-75f781d52eb5.png)

# おわりに
TiledMapEditorにはタイルレイヤーに加えてオブジェクトレイヤーという概念もありますが、こちらは別の機会にまとめたいと思います。
⇒[こちらの記事](https://qiita.com/raichi/items/5955f3e98f5ae995e57f)にまとめました。