/// <summary> /// Initializes, Reads this Map's XML info /// </summary> /// <param name="document">NanoXMLDocument containing Map's XML</param> void ParseMapXML(NanoXMLDocument document) { MapNode = document.RootNode; Orientation orientation = (Orientation)Enum.Parse(typeof(Orientation), MapNode.GetAttribute("orientation").Value, true); int width = int.Parse(MapNode.GetAttribute("width").Value, CultureInfo.InvariantCulture); int height = int.Parse(MapNode.GetAttribute("height").Value, CultureInfo.InvariantCulture); int tileWidth = int.Parse(MapNode.GetAttribute("tilewidth").Value, CultureInfo.InvariantCulture); int tileHeight = int.Parse(MapNode.GetAttribute("tileheight").Value, CultureInfo.InvariantCulture); if (MapNode.GetAttribute("version") != null) { Version = MapNode.GetAttribute("version").Value; } else Version = string.Empty; RenderOrder mapRenderOrder = RenderOrder.Right_Down; if (MapNode.GetAttribute("renderorder") != null) { string renderOrder = MapNode.GetAttribute("renderorder").Value; mapRenderOrder = (RenderOrder)Enum.Parse(typeof(RenderOrder), renderOrder.Replace('-', '_'), true); } StaggerAxis mapStaggerAxis = StaggerAxis.Y; if (MapNode.GetAttribute("staggeraxis") != null) { string staggeraxis = MapNode.GetAttribute("staggeraxis").Value; mapStaggerAxis = (StaggerAxis)Enum.Parse(typeof(StaggerAxis), staggeraxis, true); } StaggerIndex mapStaggerIndex = StaggerIndex.Odd; if (MapNode.GetAttribute("staggerindex") != null) { string staggerindex = MapNode.GetAttribute("staggerindex").Value; mapStaggerIndex = (StaggerIndex)Enum.Parse(typeof(StaggerIndex), staggerindex, true); } int hexSideLength = 0; if (MapNode.GetAttribute("hexsidelength") != null) { hexSideLength = int.Parse(MapNode.GetAttribute("hexsidelength").Value, CultureInfo.InvariantCulture); } if (MapNode.GetAttribute("nextobjectid") != null) { NextObjectID = int.Parse(MapNode.GetAttribute("nextobjectid").Value, CultureInfo.InvariantCulture); } else NextObjectID = 0; Color32 backgroundColor = new Color32(128, 128, 128, 255); if (MapNode.GetAttribute("backgroundcolor") != null) { string color = MapNode.GetAttribute("backgroundcolor").Value; string r = color.Substring(1, 2); string g = color.Substring(3, 2); string b = color.Substring(5, 2); backgroundColor = new Color32( (byte)Convert.ToInt32(r, 16), (byte)Convert.ToInt32(g, 16), (byte)Convert.ToInt32(b, 16),255); } MapRenderParameter = new MapRenderParameters(orientation, mapRenderOrder, mapStaggerAxis, mapStaggerIndex, width, height, tileWidth, tileHeight, hexSideLength, backgroundColor); if (_mapName == null) _mapName = "Map"; if (!_mapPath.EndsWith(Path.AltDirectorySeparatorChar.ToString())) _mapPath = _mapPath + Path.AltDirectorySeparatorChar; NanoXMLNode propertiesElement = MapNode["properties"]; if (propertiesElement != null) { Properties = new PropertyCollection(propertiesElement); } TileSets = new List<TileSet>(); Tiles = new Dictionary<int, Tile>(); _tileSetsToLoaded = 0; _numberOfTileSetsToLoad = 0; // First get how many tilesets we need to load foreach (NanoXMLNode node in MapNode.SubNodes) { if (node.Name.Equals("tileset")) _numberOfTileSetsToLoad++; } // Maps might not have any tileset, being just a tool for object placement :P if (_numberOfTileSetsToLoad < 1) { ContinueLoadingTiledMapAfterTileSetsLoaded(); } // Then load all of them. After all loaded, continue with map loading foreach (NanoXMLNode node in MapNode.SubNodes) { if (node.Name.Equals("tileset")) { if (node.GetAttribute("source") != null) { int firstID = int.Parse(node.GetAttribute("firstgid").Value, CultureInfo.InvariantCulture); if (UsingStreamingAssetsPath) { // Run coroutine for www using TaskManager new Task(LoadExternalTileSet(node, _mapPath, firstID), true); } else { // Parse the path string path = Utils.XUniTMXHelpers.ParsePath(_mapPath, node.GetAttribute("source").Value); TextAsset externalTileSetTextAsset = Resources.Load<TextAsset>(path); BuildExternalTileSet(externalTileSetTextAsset.text, Directory.GetParent(path).ToString(), firstID); } } else { OnFinishedLoadingTileSet(new TileSet(node, _mapPath, this, UsingStreamingAssetsPath)); } } } }
/// <summary> /// Scale this object's dimensions using map's tile size. /// We need to do this as Tiled saves object dimensions in Pixels, but we need to convert it to Unity's Unit /// </summary> /// <param name="mrp">The MapRenderParameters to which the object will be scaled</param> public static Object ScaleObject(this Object obj, MapRenderParameters mrp) { float x = 0, y = 0, width = 0, height = 0; switch (mrp.Orientation) { case Orientation.Isometric: // In Isometric maps, we must consider tile width == height for objects so their size can be correctly calculated return ScaleObjectHelper(obj, mrp.TileHeight, mrp.TileHeight); case Orientation.Staggered: // In Staggered maps, we must pre-alter object position and size, as it comes mixed between staggered and orthogonal properties x = obj.Bounds.x / (float)mrp.TileWidth; y = obj.Bounds.y / (float)mrp.TileHeight * 2.0f; width = obj.Bounds.width / (float)mrp.TileWidth; height = obj.Bounds.height / (float)mrp.TileWidth; if (mrp.MapStaggerAxis.Equals(StaggerAxis.Y)) { if ((mrp.MapStaggerIndex.Equals(StaggerIndex.Odd) && Mathf.FloorToInt(Mathf.Abs(y)) % 2 > 0) || (mrp.MapStaggerIndex.Equals(StaggerIndex.Even) && Mathf.FloorToInt(Mathf.Abs(y)) % 2 < 1)) x -= 0.5f; } else { x *= 2; y /= 2; if ((mrp.MapStaggerIndex.Equals(StaggerIndex.Odd) && Mathf.FloorToInt(Mathf.Abs(x)) % 2 > 0) || (mrp.MapStaggerIndex.Equals(StaggerIndex.Even) && Mathf.FloorToInt(Mathf.Abs(x)) % 2 < 1)) y -= 0.5f; } obj.Bounds = new Rect(x, y, width, height); if (obj.Points != null) { for (int i = 0; i < obj.Points.Count; i++) { obj.Points[i] = new Vector2(obj.Points[i].x / (float)mrp.TileWidth, obj.Points[i].y / (float)mrp.TileHeight * 2.0f); } } return obj; case Orientation.Hexagonal: // In Hexagonal maps, we must pre-alter object position and size, as it comes mixed between staggered and orthogonal properties float halfGap = 1; float tileDisplacement = 1; if (mrp.MapStaggerAxis.Equals(StaggerAxis.Y)) { halfGap = (mrp.TileHeight - mrp.HexSideLength) / 2.0f; tileDisplacement = halfGap + mrp.HexSideLength; x = obj.Bounds.x / mrp.TileWidth; y = obj.Bounds.y / (tileDisplacement / (float)mrp.TileHeight) / (float)mrp.TileHeight; if (InAStaggeredRowOrColumn(mrp.MapStaggerIndex, y)) x -= 0.5f; if (obj.Points != null) { for (int i = 0; i < obj.Points.Count; i++) { obj.Points[i] = new Vector2( obj.Points[i].x / mrp.TileWidth, obj.Points[i].y / (tileDisplacement / (float)mrp.TileHeight) / (float)mrp.TileHeight ); if (InAStaggeredRowOrColumn(mrp.MapStaggerIndex, obj.Points[i].y)) obj.Points[i] -= new Vector2(0.5f, 0); } } } else { halfGap = (mrp.TileWidth - mrp.HexSideLength) / 2.0f; tileDisplacement = halfGap + mrp.HexSideLength; x = obj.Bounds.x / tileDisplacement; y = obj.Bounds.y / (mrp.TileHeight / (float)mrp.TileWidth) / (float)mrp.TileHeight; if (InAStaggeredRowOrColumn(mrp.MapStaggerIndex, x)) y -= 0.5f * (mrp.TileHeight / (float)mrp.TileWidth); if (obj.Points != null) { for (int i = 0; i < obj.Points.Count; i++) { obj.Points[i] = new Vector2( obj.Points[i].x / tileDisplacement, obj.Points[i].y / (mrp.TileHeight / (float)mrp.TileWidth) / (float)mrp.TileHeight ); if (InAStaggeredRowOrColumn(mrp.MapStaggerIndex, obj.Points[i].x)) obj.Points[i] -= new Vector2(0, 0.5f * (mrp.TileHeight / (float)mrp.TileWidth)); } } } width = obj.Bounds.width / (float)mrp.TileWidth; height = obj.Bounds.height / (float)mrp.TileHeight; obj.Bounds = new Rect(x, y, width, height); return obj; default: return ScaleObjectHelper(obj, mrp.TileWidth, mrp.TileHeight); } }