Exemplo n.º 1
0
        /// <summary>
        /// TMXファイルのロードと構築
        /// </summary>
        /// <remarks>
        /// Tiled Map Editor の TMX 形式のマップ ファイルを読み込んで、
        /// このノードの下に再構築します。
        /// タイルのプロパティで"Name"という名前のものを設定しておくと、その名前でノードを作成します。
        /// <note>
        /// "Orthogonal"でも"Isometric"でもノード位置はまったく同じ。
        /// "Isometric"の場合マップが菱形になるようにスプライトのオフセットが設定される。
        /// コリジョンなどは"Orthogonal"と同一の物を使うべし。
        /// </note>
        /// </remarks>
        /// <param name="fileName">マップ ファイル名</param>
        /// <returns></returns>
        public bool LoadFromFile(string fileName)
        {
            if (Node == null) {
                throw new InvalidOperationException ("This component is not attached");
            }
            var map = new TmxMap (fileName);
            if (map == null) {
                return false;
            }
            if (!(map.Orientation == TmxMap.OrientationType.Orthogonal || map.Orientation == TmxMap.OrientationType.Isometric)) {
                throw new NotImplementedException ("Sorry, Orthogonal or Isometric only!");
            }

            // マップ情報
            //this.Node.Name = fileName;
            this.orientaion = map.Orientation.ToString ();
            this.width = map.Width;
            this.height = map.Height;
            this.tileWidth = map.TileWidth;
            this.tileHeight = map.TileHeight;
            this.mapLayers.Clear ();
            this.objLayers.Clear ();
            this.imgLayers.Clear ();
            foreach (var prop in map.Properties) {
                this.Node.UserData.Add (prop.Key, prop.Value);
            }

            var texIds = new Dictionary<string, string> ();

            // 使用するタイル セットのロード
            foreach (var tileset in map.Tilesets) {
                var data = tileset.Image.Data;
                if (data != null) {
                    // 現在のところ画像埋め込み型(data != null)には対応していません。
                    // (そもそもエディターが対応してないので作れない)
                    // data は GZipStream または ZlibStream 。両方とも stream から派生してるのがめんどくさそう。
                    throw new NotImplementedException ("Sorry, Embedded image is not implemented");
                }
                var src = tileset.Image.Source;
                if (src != null) {
                    Resource.GetTexture (src);
                    texIds.Add (tileset.Name, src);
                }
            }

            // タイル レイヤー
            foreach (var layer in map.Layers) {
                var layerNode = new Node (layer.Name);
                layerNode.Visible = layer.Visible;
                layerNode.Opacity = (float)layer.Opacity;
                foreach (var prop in layer.Properties) {
                    layerNode.UserData.Add (prop.Key, prop.Value);
                }
                var layerComp = new GridMap (width, height);
                layerComp.TileWidth = tileWidth;
                layerComp.TileHeight = tileHeight;
                layerNode.Attach (layerComp);

                foreach (var tile in layer.Tiles) {
                    var x = tile.X;       // マップ座標系(タイル単位)
                    var y = tile.Y;
                    var gid = tile.Gid;
                    if (gid != 0) {
                        var tileset = map.Tilesets.Last (t => t.FirstGid <= gid);
                        var id = gid - tileset.FirstGid;
                        var tex = Resource.GetTexture (texIds[tileset.Name]);
                        var hTileNum = (tex.Width - tileset.Margin * 2 + tileset.Spacing) / (tileset.TileWidth + tileset.Spacing);
                        var ix = id % hTileNum;
                        var iy = id / hTileNum;
                        var tx = tileset.TileOffset.X + tileset.Margin + (tileset.TileWidth + tileset.Spacing) * ix;
                        var ty = tileset.TileOffset.Y + tileset.Margin + (tileset.TileHeight + tileset.Spacing) * iy;

                        var name = layer.Name + "[" + x + "," + y + "]";
                        var tileNode = new Node (name);
                        tileNode.Translation = new Vector3 (x * TileWidth, y * TileHeight, 0);

                        var spr = new Sprite (tileset.TileWidth, tileset.TileHeight);
                        spr.AddTexture (tex);
                        spr.SetTextureOffset (tx, ty);
                        if (orientaion == "Isometric") {
                            // ノード位置 : Port
                            // 表示位置 : Piso
                            // スプライトのオフセット : Piso - Port
                            var sx = -x * TileWidth / 2 - y * TileWidth / 2;
                            var sy = x * TileHeight / 2 - y * TileHeight / 2;
                            spr.SetOffset (sx, sy);
                        }
                        tileNode.Attach (spr);

                        layerNode.AddChild (tileNode);
                        layerComp[y, x] = tileNode;
                    }
                }

                this.Node.AddChild (layerNode);
                this.mapLayers.Add (layerNode);
            }

            // オブジェクト レイヤー
            foreach (var layer in map.ObjectGroups) {
                var layerNode = new Node (layer.Name);
                layerNode.Visible = layer.Visible;
                layerNode.Opacity = (float)layer.Opacity;
                foreach (var prop in layer.Properties) {
                    layerNode.UserData.Add (prop.Key, prop.Value);
                }

                foreach (var obj in layer.Objects) {
                    var objNode = new Node (obj.Name);
                    objNode.SetTranslation (obj.X, obj.Y, 0);

                    var type = Type.GetType (obj.Type);
                    if (type != null) {
                        var comp = Activator.CreateInstance (type) as Component;
                        if (comp != null) {
                            foreach (var prop in obj.Properties) {
                                var propInfo = comp.GetType ().GetProperty (prop.Key);
                                if (propInfo != null) {
                                    SetPropertyValue (comp, propInfo, (string)prop.Value);
                                }
                            }
                            objNode.Attach (comp);
                        }
                    }
                    var p = obj.Points;
                    var pt = obj.Tile;

                    layerNode.AddChild (objNode);
                }

                this.Node.AddChild (layerNode);
                this.objLayers.Add (layerNode);
            }

            // 画像レイヤー
            foreach (var layer in map.ImageLayers) {
                var layerNode = new Node (layer.Name);
                layerNode.Visible = layer.Visible;
                layerNode.Opacity = (float)layer.Opacity;
                foreach (var prop in layer.Properties) {
                    layerNode.UserData.Add (prop.Key, prop.Value);
                }

                var src = layer.Image.Source;
                if (src != null) {
                    var layerComp = new Sprite ();
                    layerComp.AddTexture (Resource.GetTexture (src));
                    layerNode.Attach (layerComp);
                }
                var data = layer.Image.Data;
                if (data != null) {
                    throw new NotImplementedException ("Sorry, Embedded image is not implemented");
                }

                this.Node.AddChild (layerNode);
            }

            return true;
        }