// TODO: Support for zlib compression of tile data (Zlib.NET) // http://stackoverflow.com/questions/6620655/compression-and-decompression-problem-with-zlib-net // Reads and converts and .tmx file to a TiledMap object. Doing so does NOT load appropriate tile textures into memory. // In order for textures to be loaded, the LoadContent(ContentManager) method must be called. This is usually automatically // performed by the TeeEngine when calling its LoadMap(TiledMap) method. However, it may be called independently if needs be. public static TiledMap LoadTmxFile(string file) { if (File.Exists(file)) { // Find the working directory of this file so that any external files may use the same path. int dirIndex = file.LastIndexOfAny(new char[] { '/', '\\' }); string workingDirectory = (dirIndex > 0) ? file.Substring(0, dirIndex) : ""; XmlDocument document = new XmlDocument(); document.Load(file); XmlNode mapNode = document.SelectSingleNode("map"); TiledMap map = new TiledMap(); map.txWidth = XmlExtensions.GetAttributeValue<int>(mapNode, "width", -1, true); map.txHeight = XmlExtensions.GetAttributeValue<int>(mapNode, "height", -1, true); map.TileWidth = XmlExtensions.GetAttributeValue<int>(mapNode, "tilewidth", -1, true); map.TileHeight = XmlExtensions.GetAttributeValue<int>(mapNode, "tileheight", -1, true); map.TileDiagonalLength = Math.Sqrt(Math.Pow(map.TileWidth, 2) + Math.Pow(map.TileHeight, 2)); map.Background = ColorExtensions.ToColor( XmlExtensions.GetAttributeValue( mapNode, "backgroundcolor", "#000000" ) ); map.LoadProperties(mapNode); // OBJECT LAYERS foreach (XmlNode objectLayerNode in mapNode.SelectNodes("objectgroup")) { TiledObjectLayer mapObjectLayer = new TiledObjectLayer(); mapObjectLayer.Width = XmlExtensions.GetAttributeValue<int>(objectLayerNode, "width", 1); mapObjectLayer.Height = XmlExtensions.GetAttributeValue<int>(objectLayerNode, "height", 1); mapObjectLayer.Name = XmlExtensions.GetAttributeValue(objectLayerNode, "name"); foreach (XmlNode objectNode in objectLayerNode.SelectNodes("object")) { TiledObject mapObject = new TiledObject(); mapObject.Name = XmlExtensions.GetAttributeValue(objectNode, "name"); mapObject.Type = XmlExtensions.GetAttributeValue(objectNode, "type"); mapObject.X = XmlExtensions.GetAttributeValue<int>(objectNode, "x", 0); mapObject.Y = XmlExtensions.GetAttributeValue<int>(objectNode, "y", 0); mapObject.Width = XmlExtensions.GetAttributeValue<int>(objectNode, "width", 0); mapObject.Height = XmlExtensions.GetAttributeValue<int>(objectNode, "height", 0); mapObject.Gid = XmlExtensions.GetAttributeValue<int>(objectNode, "gid", -1); XmlNode polygonNode = objectNode.SelectSingleNode("polygon"); if (polygonNode != null) mapObject.Points = ConvertToPointsList(XmlExtensions.GetAttributeValue(polygonNode, "points")); mapObject.LoadProperties(objectNode); mapObjectLayer.TiledObjects.Add(mapObject); } map.TiledObjectLayers.Add(mapObjectLayer); } // TILESETS foreach (XmlNode tilesetNode in mapNode.SelectNodes("tileset")) { XmlNode actualTilesetNode; int firstGID = XmlExtensions.GetAttributeValue<int>(tilesetNode, "firstgid", -1, true); // If the tileset comes from an external .tsx file, load the node from that file. if (XmlExtensions.HasAttribute(tilesetNode, "source")) { XmlDocument tilesetDocument = new XmlDocument(); tilesetDocument.Load( string.Format("{0}/{1}", workingDirectory, XmlExtensions.GetAttributeValue(tilesetNode, "source"))); actualTilesetNode = tilesetDocument.SelectSingleNode("tileset"); } else actualTilesetNode = tilesetNode; string tilesetName = XmlExtensions.GetAttributeValue(actualTilesetNode, "name"); int tileHeight = XmlExtensions.GetAttributeValue<int>(actualTilesetNode, "tileheight", -1, true); int tileWidth = XmlExtensions.GetAttributeValue<int>(actualTilesetNode, "tilewidth", -1, true); TileSet tileset = new TileSet(); tileset.LoadProperties(actualTilesetNode); tileset.Name = tilesetName; tileset.TileWidth = tileWidth; tileset.TileHeight = tileHeight; tileset.ContentTexturePath = tileset.GetProperty("Content"); // Content Texture Path for XNA. REQUIRED. map.TileSets.Add(tileset); XmlNode imageNode = actualTilesetNode.SelectSingleNode("image"); int imageWidth = XmlExtensions.GetAttributeValue<int>(imageNode, "width", -1, true); int imageHeight = XmlExtensions.GetAttributeValue<int>(imageNode, "height", -1, true); string sourceTexturePath = XmlExtensions.GetAttributeValue<string>(imageNode, "source", "", true); // PreBuild the tiles from the tileset information. int i = 0; while (true) { int tx = (i * tileWidth) % imageWidth; int ty = tileHeight * ((i * tileWidth) / imageWidth); // This check is performed in the case where image width is not // an exact multiple of the tile width specified. if (tx + tileWidth > imageWidth) { tx = 0; ty += tileHeight; } // If we have exceeded the image height, we are done. if (ty + tileHeight > imageHeight) break; Tile tile = new Tile(); tile.SourceTexturePath = sourceTexturePath; // Path to the actual file being referred. tile.SourceRectangle = new Rectangle(tx, ty, tileWidth, tileHeight); tile.TileGid = i + firstGID; tile.TileId = i; tile.TileSet = tileset; map.Tiles.Add(tile.TileGid, tile); tileset.Tiles.Add(i, tile); i++; } // Add any individual properties to the tiles we have created foreach (XmlNode tileNode in actualTilesetNode.SelectNodes("tile")) { int tileGid = firstGID + XmlExtensions.GetAttributeValue<int>(tileNode, "id", -1, true); Tile tile = map.Tiles[tileGid]; tile.LoadProperties(tileNode); // BUILT INS // Adjust the draw origin based on the tile property 'DrawOrigin' string[] drawOrigin = tile.GetProperty("DrawOrigin", "0, 1").Split(','); tile.Origin = new Vector2( (float)Convert.ToDouble(drawOrigin[0]), (float)Convert.ToDouble(drawOrigin[1]) ); } } // TILE LAYERS foreach (XmlNode layerNode in mapNode.SelectNodes("layer")) { int width = XmlExtensions.GetAttributeValue<int>(layerNode, "width", 0); int height = XmlExtensions.GetAttributeValue<int>(layerNode, "height", 0); TileLayer tileLayer = new TileLayer(width, height); tileLayer.Name = XmlExtensions.GetAttributeValue(layerNode, "name"); tileLayer.LoadProperties(layerNode); // SET BUILTIN PROPERTIES tileLayer.Color = ColorExtensions.ToColor( tileLayer.GetProperty<string>("Color", "#ffffff") ); tileLayer.Opacity = tileLayer.GetProperty<float>("Opacity", 1.0f); XmlNode dataNode = layerNode.SelectSingleNode("data"); string[] tokens = dataNode.InnerText.Split( new char[] { '\n', ',', '\r' }, StringSplitOptions.RemoveEmptyEntries ); for (int index = 0; index < tokens.Length; index++) tileLayer[index] = Convert.ToInt32(tokens[index]); map.TileLayers.Add(tileLayer); } return map; } else throw new IOException(string.Format("The Map File '{0}' does not exist.", file)); }