public LayerObject(int id, int width, int height, int x, int y, string type, LayerCustomProperties properties, LayerAnimationInfo animation) { bool isScaled = true; Id = id; Width = width; Height = height; X = x; Y = y; if (type != "collision") { Y -= height; } SetDestinationRectangle(isScaled); Type = type; if (properties != null) { Direction = properties.Direction; MoveSpeed = properties.MoveSpeed; if (properties.Source.HasValue) { Source = new Rectangle((int)properties.Source.Value.X, (int)properties.Source.Value.Y, Width, Height); } if (properties.Collision.HasValue) { Collision = new Rectangle( (int)(properties.Collision.Value.X * GlobalConstants.Scale) + DestinationRectangle.X, (int)(properties.Collision.Value.Y * GlobalConstants.Scale) + DestinationRectangle.Y, (int)(properties.Collision.Value.Width * GlobalConstants.Scale), (int)(properties.Collision.Value.Height * GlobalConstants.Scale) ); } ToId = properties.ToId; ToMap = properties.ToMap; } if (animation != null) { AnimationRandomness = animation.Randomness; LayerAnimationSource[] animationSequenceSource = animation.Sequence; AnimationSequence = new List <Rectangle>(); foreach (LayerAnimationSource s in animationSequenceSource) { AnimationSequence.Add(new Rectangle((int)s.Source.X, (int)s.Source.Y, Width, Height)); } } }
/// <summary> /// Reloads the tmx file and regenerates the 2D map /// </summary> private void ReloadMap(string mapFile) { while (rootTransform.childCount > 0) { for (int i = 0; i < rootTransform.childCount; i++) { GameObject child = rootTransform.GetChild(i).gameObject; DestroyImmediate(child); } } XmlSerializer mapFileReader = new XmlSerializer(typeof(TiledMap)); string mapFolder = mapFile.Substring(0, mapFile.LastIndexOfAny(FILEPATH_SEPARATORS) + 1); TiledMap map = null; using (XmlTextReader reader = new XmlTextReader(mapFile)) { map = (TiledMap)mapFileReader.Deserialize(reader); } if (map == null || map.layers == null || map.layers.Length == 0) { return; } if (map.tileSetEntries != null && map.tileSetEntries.Length > 0) { map.tileSets = new TiledTileSetFile[map.tileSetEntries.Length]; XmlSerializer tileSetFileReader = new XmlSerializer(typeof(TiledTileSetFile)); for (int i = 0; i < map.tileSetEntries.Length; i++) { string tileSetFile = map.tileSetEntries[i].source; List <string> mapFolderParts = new List <string>(mapFolder.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)); List <string> tileSetFileParts = new List <string>(tileSetFile.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)); string pathStart = tileSetFileParts[0]; while (pathStart == "..") { tileSetFileParts.RemoveAt(0); mapFolderParts.RemoveAt(mapFolderParts.Count - 1); pathStart = tileSetFileParts[0]; } string tileSetPath = string.Join("/", new string[] { string.Join("/", mapFolderParts.ToArray()), string.Join("/", tileSetFileParts.ToArray()) }); using (XmlTextReader reader = new XmlTextReader(tileSetPath)) { map.tileSets[i] = (TiledTileSetFile)tileSetFileReader.Deserialize(reader); } string loc = Application.dataPath.Replace("Assets", "") + tileSetPath; tsxOriginalLocations.Add(loc); } } int z = 0; for (int l = map.layers.Length - 1; l >= 0; l--) { TiledLayer layer = map.layers[l]; spriteCache = new List <Sprite>(); usedTiles = new List <int>(); int w, h; w = layer.width; h = layer.height; GameObject layerObject = new GameObject(layer.name); layerObject.transform.parent = rootTransform; layerObject.isStatic = true; TiledProperty[] layerProperties = layer.customProperties; if (layerProperties != null && layerProperties.Length > 0) { LayerCustomProperties properties = layerObject.AddComponent <LayerCustomProperties>(); for (int i = 0; i < layerProperties.Length; i++) { if (layerProperties[i].name.ToLower().Equals("height")) { float constantHeight; if (float.TryParse(layerProperties[i].value, out constantHeight)) { properties.height = constantHeight; } } } } string[] layerData = layer.data.Value.Trim().Split(ROW_SEPARATOR, System.StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < h; i++) { string[] row = layerData[i].Split(COMMA_SEPARATOR); for (int j = 0; j < w; j++) { uint tid = uint.Parse(row[j]); bool flipX = (tid & FLIPPED_HORIZONTALLY_FLAG) >> 31 == 1; tid &= ~FLIPPED_HORIZONTALLY_FLAG; bool flipY = (tid & FLIPPED_VERTICALLY_FLAG) >> 30 == 1; tid &= ~FLIPPED_VERTICALLY_FLAG; bool flipDiag = (tid & FLIPPED_DIAGONALLY_FLAG) >> 29 == 1; tid &= ~FLIPPED_DIAGONALLY_FLAG; int tileID = (int)tid; if (tileID != 0) { Vector3 tilePosition = new Vector3((w * -0.5f) + j, (h * 0.5f) - i, 0); GameObject tileObject = new GameObject("TILE[" + i + "," + j + "]"); tileObject.isStatic = true; tileObject.transform.position = tilePosition; tileObject.transform.parent = layerObject.transform; //tileObject.transform.localScale = new Vector3(1.01f, 1.01f, 1.0f); SpriteRenderer sr = tileObject.AddComponent <SpriteRenderer>(); sr.sortingOrder = z; if (flipDiag) { tileObject.transform.Rotate(0, 0, 90); tileObject.transform.localScale = new Vector3(1, -1, 1); } sr.flipX = flipX; sr.flipY = flipY; int spriteIndex = usedTiles.IndexOf(tileID); if (spriteIndex < 0) { //new tile Sprite sp = GetTile(tileID, map); spriteCache.Add(sp); usedTiles.Add(tileID); sr.sprite = sp; } else { sr.sprite = spriteCache[spriteIndex]; } AnimationFrame[] frames = GetAnimations(tileID, map); if (frames != null) { AnimatedSprite anim = tileObject.AddComponent <AnimatedSprite>(); anim.frames = frames; } //Add colliders TiledObjectGroup group = GetObjectsGroup(map, tileID); if (group != null && group.objects != null) { float ppu = sr.sprite.pixelsPerUnit; Collider2D col; foreach (TiledTObject obj in group.objects) { if (obj.polygon != null) { Vector2 startPoint = new Vector2(obj.x / ppu - 0.5f, -obj.y / ppu + 0.5f); Vector2[] points = obj.polygon.GetPoints(); for (int k = 0; k < points.Length; k++) { points[k].x /= ppu; points[k].y /= -ppu; points[k].x += startPoint.x; points[k].y += startPoint.y; } col = tileObject.AddComponent <PolygonCollider2D>(); RotatePoints(points, -obj.rotation, points[0]); if (flipY) { RotatePoints(points, 180.0f, Vector3.zero); } ((PolygonCollider2D)col).points = points; } else if (obj.polyline != null) { Vector2 startPoint = new Vector2(obj.x / ppu - 0.5f, -obj.y / ppu + 0.5f); Vector2[] points = obj.polyline.GetPoints(); for (int k = 0; k < points.Length; k++) { points[k].x /= ppu; points[k].y /= -ppu; points[k].x += startPoint.x; points[k].y += startPoint.y; } col = tileObject.AddComponent <EdgeCollider2D>(); RotatePoints(points, -obj.rotation, points[0]); ((EdgeCollider2D)col).points = points; } else if (obj.ellipse != null) { Vector2 center = new Vector2(obj.x / ppu - 0.5f, -obj.y / ppu + 0.5f); float width = obj.width / ppu; float height = obj.height / ppu; center.x += width / 2.0f; center.y -= height / 2.0f; if (Mathf.Abs(width - height) < 0.1f) { col = tileObject.AddComponent <CircleCollider2D>(); float radius = Mathf.Max(height, width) / 2.0f; ((CircleCollider2D)col).radius = radius; } else { int vertices = 24; col = tileObject.AddComponent <PolygonCollider2D>(); Vector2[] points = new Vector2[vertices]; float angStep = 360.0f / vertices; Vector2 rotationCenter = new Vector2(float.MaxValue, float.MinValue); for (int p = 0; p < points.Length; p++) { float ang = angStep * p * Mathf.Deg2Rad; float x = width * Mathf.Cos(ang) * 0.5f; float y = height * Mathf.Sin(ang) * 0.5f; points[p] = new Vector2(x, y); if (x < rotationCenter.x) { rotationCenter.x = x; } if (y > rotationCenter.y) { rotationCenter.y = y; } } RotatePoints(points, -obj.rotation, rotationCenter); ((PolygonCollider2D)col).points = points; } col.offset = center; } else { Vector2 offset = new Vector2(obj.x / ppu, -obj.y / ppu); float colWidth = obj.width / ppu; float colHeight = obj.height / ppu; Vector2[] points = new Vector2[4]; float x = obj.x / ppu - 0.5f; float y = -obj.y / ppu + 0.5f; points[0] = new Vector2(x, y); points[1] = new Vector2(x + colWidth, y); points[2] = new Vector2(x + colWidth, y - colHeight); points[3] = new Vector2(x, y - colHeight); RotatePoints(points, -obj.rotation, points[0]); col = tileObject.AddComponent <PolygonCollider2D>(); ((PolygonCollider2D)col).points = points; if (col != null) { col.offset += new Vector2(group.offsetX / ppu, -group.offsetY / ppu); } } } } } } } z--; } Resources.UnloadUnusedAssets(); }
/// <summary> /// Sets the heights of the layers and models in them based on specified /// constant heights or by stacking objects over one another /// </summary> private void SetLayersHeights() { int groundLayerIndex = rootTransform.childCount - 1; for (int i = 0; i < rootTransform.childCount; i++) { if (rootTransform.GetChild(i).name.Equals( "Ground", System.StringComparison.OrdinalIgnoreCase)) { groundLayerIndex = i; break; } } //Start from ground layer down for (int i = groundLayerIndex + 1; i < rootTransform.childCount; i++) { Transform child = rootTransform.GetChild(i); bool adjustToUpperLayer = true; LayerCustomProperties properties = child.GetComponent <LayerCustomProperties>(); if (properties != null && properties.height != float.MinValue) { Vector3 pos = child.position; pos.y = properties.height; child.position = pos; adjustToUpperLayer = false; } for (int t = 0; t < child.childCount; t++) { Transform myTile = child.GetChild(t); if (adjustToUpperLayer) { float minPos = float.MaxValue; int firstDashIndex = myTile.name.IndexOf('-'); float myHeight = float.Parse(myTile.name.Substring(0, firstDashIndex)); //myHeight *= transform.localScale.y; //Search in upper layers only for (int j = i - 1; j >= 0; j--) { Transform layer = rootTransform.GetChild(j); for (int k = 0; k < layer.childCount; k++) { Transform otherTile = layer.GetChild(k); float pos = otherTile.position.y - myHeight; if (pos < minPos) { minPos = pos; } } } Vector3 newPos = myTile.position; newPos.y = minPos; myTile.position = newPos; } } } //Start from ground layer up for (int i = groundLayerIndex - 1; i >= 0; i--) { Transform child = rootTransform.GetChild(i); bool adjustToLoewrLayer = true; LayerCustomProperties properties = child.GetComponent <LayerCustomProperties>(); if (properties != null && properties.height != float.MinValue) { Vector3 pos = child.position; pos.y = properties.height; child.position = pos; adjustToLoewrLayer = false; } for (int t = 0; t < child.childCount; t++) { Transform myTile = child.GetChild(t); if (adjustToLoewrLayer) { float maxHeight = 0.0f; //Search in lower layers only for (int j = i + 1; j < rootTransform.childCount; j++) { Transform layer = rootTransform.GetChild(j); for (int k = 0; k < layer.childCount; k++) { Transform otherTile = layer.GetChild(k); if (myTile.position.x == otherTile.position.x && myTile.position.z == otherTile.position.z) { Collider col = otherTile.GetComponentInChildren <Collider>(); if (col != null) { int firstDashIndex = otherTile.name.IndexOf('-'); float height = float.Parse(otherTile.name.Substring(0, firstDashIndex)); height *= myTile.localScale.y; height += otherTile.position.y; if (height > maxHeight) { maxHeight = height; } } } } } myTile.Translate(0, maxHeight, 0, Space.World); } } } }