예제 #1
0
        protected override void InternalFromXml(System.Xml.Linq.XElement xml, TmxMap tmxMap)
        {
            // Get the tile
            uint gid = TmxHelper.GetAttributeAsUInt(xml, "gid");
            this.Tile = tmxMap.Tiles[gid];

            // Our size is given by the tile
            this.Size = this.Tile.TileSize;
        }
예제 #2
0
        public Point GetMapPositionAt(int x, int y, TmxTile tile)
        {
            Point point = GetMapPositionAt(x, y);

            // The tile may have different dimensions than the cells of the map so correct for that
            // In this case, the y-position needs to be adjusted
            point.Y = (point.Y + this.TileHeight) - tile.TileSize.Height;

            return point;
        }
        private PointF[] CalculateFaceTextureCoordinates(TmxTile tmxTile, bool flipDiagonal, bool flipHorizontal, bool flipVertical)
        {
            Point imageLocation = tmxTile.LocationOnSource;
            Size tileSize = tmxTile.TileSize;
            Size imageSize = tmxTile.TmxImage.Size;

            PointF[] points = new PointF[4];
            points[0] = imageLocation;
            points[1] = PointF.Add(imageLocation, new Size(tileSize.Width, 0));
            points[2] = PointF.Add(imageLocation, tileSize);
            points[3] = PointF.Add(imageLocation, new Size(0, tileSize.Height));

            PointF center = new PointF(tileSize.Width * 0.5f, tileSize.Height * 0.5f);
            center.X += imageLocation.X;
            center.Y += imageLocation.Y;
            TmxMath.TransformPoints_DiagFirst(points, center, flipDiagonal, flipHorizontal, flipVertical);
            //TmxMath.TransformPoints(points, center, flipDiagonal, flipHorizontal, flipVertical);

            PointF[] coordinates = new PointF[4];
            coordinates[3] = PointToTextureCoordinate(points[0], imageSize);
            coordinates[2] = PointToTextureCoordinate(points[1], imageSize);
            coordinates[1] = PointToTextureCoordinate(points[2], imageSize);
            coordinates[0] = PointToTextureCoordinate(points[3], imageSize);

            // Apply a small bias to the "inner" edges of the texels
            // This keeps us from seeing seams
            //const float bias = 1.0f / 8192.0f;
            //const float bias = 1.0f / 4096.0f;
            //const float bias = 1.0f / 2048.0f;
            if (Tiled2Unity.Settings.TexelBias > 0)
            {
                float bias = 1.0f / Tiled2Unity.Settings.TexelBias;

                PointF[] multiply = new PointF[4];
                multiply[0] = new PointF(1, 1);
                multiply[1] = new PointF(-1, 1);
                multiply[2] = new PointF(-1, -1);
                multiply[3] = new PointF(1, -1);

                // This nudge has to be transformed too
                TmxMath.TransformPoints_DiagFirst(multiply, Point.Empty, flipDiagonal, flipHorizontal, flipVertical);

                coordinates[0] = TmxMath.AddPoints(coordinates[0], TmxMath.ScalePoints(multiply[0], bias));
                coordinates[1] = TmxMath.AddPoints(coordinates[1], TmxMath.ScalePoints(multiply[1], bias));
                coordinates[2] = TmxMath.AddPoints(coordinates[2], TmxMath.ScalePoints(multiply[2], bias));
                coordinates[3] = TmxMath.AddPoints(coordinates[3], TmxMath.ScalePoints(multiply[3], bias));
            }

            return coordinates;
        }
예제 #4
0
        private void ParseTilesetFromImageLayer(XElement elemImageLayer)
        {
            string tilesetName = TmxHelper.GetAttributeAsString(elemImageLayer, "name");

            XElement xmlImage = elemImageLayer.Element("image");
            if (xmlImage == null)
            {
                Logger.WriteWarning("Image Layer '{0}' has no image assigned.", tilesetName);
                return;
            }

            TmxImage tmxImage = TmxImage.FromXml(xmlImage);

            // The "firstId" is is always one more than all the tiles that we've already parsed (which may be zero)
            uint firstId = 1;
            if (this.Tiles.Count > 0)
            {
                firstId = this.Tiles.Max(t => t.Key) + 1;
            }

            uint localId = 1;
            uint globalId = firstId + localId;

            TmxTile tile = new TmxTile(globalId, localId, tilesetName, tmxImage);
            tile.SetTileSize(tmxImage.Size.Width, tmxImage.Size.Height);
            tile.SetLocationOnSource(0, 0);
            this.Tiles[tile.GlobalId] = tile;
        }
예제 #5
0
        // This method is called eventually for external tilesets too
        // Only the gid attribute has been consumed at this point for the tileset
        private void ParseInternalTileset(XElement elemTileset, uint firstId)
        {
            string tilesetName = TmxHelper.GetAttributeAsString(elemTileset, "name");

            Logger.WriteLine("Parse internal tileset '{0}' (gid = {1}) ...", tilesetName, firstId);

            int tileWidth = TmxHelper.GetAttributeAsInt(elemTileset, "tilewidth");
            int tileHeight = TmxHelper.GetAttributeAsInt(elemTileset, "tileheight");
            int spacing = TmxHelper.GetAttributeAsInt(elemTileset, "spacing", 0);
            int margin = TmxHelper.GetAttributeAsInt(elemTileset, "margin", 0);

            PointF tileOffset = PointF.Empty;
            XElement xmlTileOffset = elemTileset.Element("tileoffset");
            if (xmlTileOffset != null)
            {
                tileOffset.X = TmxHelper.GetAttributeAsInt(xmlTileOffset, "x");
                tileOffset.Y = TmxHelper.GetAttributeAsInt(xmlTileOffset, "y");
            }

            IList<TmxTile> tilesToAdd = new List<TmxTile>();

            // Tilesets may have an image for all tiles within it, or it may have an image per tile
            if (elemTileset.Element("image") != null)
            {
                TmxImage tmxImage = TmxImage.FromXml(elemTileset.Element("image"));

                // Create all the tiles
                // This is a bit complicated because of spacing and margin
                // (Margin is ignored from Width and Height)
                for (int end_y = margin + tileHeight; end_y <= tmxImage.Size.Height; end_y += spacing + tileHeight)
                {
                    for (int end_x = margin + tileWidth; end_x <= tmxImage.Size.Width; end_x += spacing + tileWidth)
                    {
                        uint localId = (uint) tilesToAdd.Count();
                        uint globalId = firstId + localId;
                        TmxTile tile = new TmxTile(globalId, localId, tilesetName, tmxImage);
                        tile.Offset = tileOffset;
                        tile.SetTileSize(tileWidth, tileHeight);
                        tile.SetLocationOnSource(end_x - tileWidth, end_y - tileHeight);
                        tilesToAdd.Add(tile);
                    }
                }
            }
            else
            {
                // Each tile will have it's own image
                foreach (var t in elemTileset.Elements("tile"))
                {
                    TmxImage tmxImage = TmxImage.FromXml(t.Element("image"));

                    uint localId = (uint)tilesToAdd.Count();

                    // Local Id can be overridden by the tile element
                    // This is because tiles can be removed from the tileset, so we won'd always have a zero-based index
                    localId = TmxHelper.GetAttributeAsUInt(t, "id", localId);

                    uint globalId = firstId + localId;
                    TmxTile tile = new TmxTile(globalId, localId, tilesetName, tmxImage);
                    tile.Offset = tileOffset;
                    tile.SetTileSize(tmxImage.Size.Width, tmxImage.Size.Height);
                    tile.SetLocationOnSource(0, 0);
                    tilesToAdd.Add(tile);
                }
            }

            StringBuilder builder = new StringBuilder();
            foreach (TmxTile tile in tilesToAdd)
            {
                builder.AppendFormat("{0}", tile.ToString());
                if (tile != tilesToAdd.Last()) builder.Append("\n");
                this.Tiles[tile.GlobalId] = tile;
            }
            Logger.WriteLine("Added {0} tiles", tilesToAdd.Count);

            // Add any extra data to tiles
            foreach (var elemTile in elemTileset.Elements("tile"))
            {
                int localTileId = TmxHelper.GetAttributeAsInt(elemTile, "id");
                var tiles = from t in this.Tiles
                            where t.Value.GlobalId == localTileId + firstId
                            select t.Value;

                // Note that some old tile data may be sticking around
                if (tiles.Count() == 0)
                {
                    Logger.WriteWarning("Tile '{0}' in tileset '{1}' does not exist but there is tile data for it.\n{2}", localTileId, tilesetName, elemTile.ToString());
                }
                else
                {
                    tiles.First().ParseTileXml(elemTile, this, firstId);
                }
            }
        }
예제 #6
0
        private void ParseTilesetFromImageLayer(XElement elemImageLayer)
        {
            string tilesetName = TmxHelper.GetAttributeAsString(elemImageLayer, "name");

            XElement xmlImage = elemImageLayer.Element("image");
            if (xmlImage == null)
            {
                Program.WriteWarning("Image Layer '{0}' has no image assigned.", tilesetName);
                return;
            }

            TmxImage tmxImage = TmxImage.FromXml(xmlImage);

            uint firstId = this.Tiles.Max(t => t.Key) + 1;
            uint localId = 1;
            uint globalId = firstId + localId;

            TmxTile tile = new TmxTile(globalId, localId, tilesetName, tmxImage);
            tile.SetTileSize(tmxImage.Size.Width, tmxImage.Size.Height);
            tile.SetLocationOnSource(0, 0);
            this.Tiles[tile.GlobalId] = tile;
        }
예제 #7
0
        private bool CanAddFrame(TmxTile tile, int startMs, int durationMs)
        {
            if (IsMeshFull())
                return false;

            if (this.TmxImage != tile.TmxImage)
                return false;

            if (this.StartTimeMs != startMs)
                return false;

            if (this.DurationMs != durationMs)
                return false;

            return true;
        }
예제 #8
0
        // Creates a TmxMesh from a tile (for tile objects)
        public static List<TmxMesh> FromTmxTile(TmxTile tmxTile, TmxMap tmxMap)
        {
            List<TmxMesh> meshes = new List<TmxMesh>();

            int timeMs = 0;
            foreach (var frame in tmxTile.Animation.Frames)
            {
                uint frameTileId = frame.GlobalTileId;
                TmxTile frameTile = tmxMap.Tiles[frameTileId];

                TmxMesh mesh = new TmxMesh();
                mesh.TileIds = new uint[1];
                mesh.TileIds[0] = frameTileId;

                mesh.UniqueMeshName = String.Format("mesh_tile_{0}", TmxMath.GetTileIdWithoutFlags(frameTileId).ToString("D4"));
                mesh.TmxImage = frameTile.TmxImage;
                mesh.ObjectName = "tile_obj";

                // Keep track of the timing for this mesh (non-animating meshes will have a start time and duration of 0)
                mesh.StartTimeMs = timeMs;
                mesh.DurationMs = frame.DurationMs;
                mesh.FullAnimationDurationMs = tmxTile.Animation.TotalTimeMs;

                if (mesh.DurationMs != 0)
                {
                    // Decorate the name a bit with some animation details for the frame
                    mesh.ObjectName += string.Format("[{0}-{1}]", timeMs, timeMs + mesh.DurationMs);
                }

                // Advance time
                timeMs += frame.DurationMs;

                // Add the animation frame to our list of meshes
                meshes.Add(mesh);
            }

            return meshes;
        }
            public static IEnumerable<TileFrame> EnumerateFramesFromTile(TmxTile tile, TmxMap map)
            {
                if (tile.Animation == null)
                {
                    // Treat the tile as a single-frame animation
                    yield return new TileFrame { Tile = tile, Position_z = 0 };
                }
                else
                {
                    // Visit all the frames of the animated tile
                    float sign = 1.0f;
                    foreach (var f in tile.Animation.Frames)
                    {
                        // The frame Id is baked into the z value of the tile
                        // (Negative values frames are not shown, so we start off with only the first tile being positive/visible)
                        float z = (float)f.UniqueFrameId * sign;
                        yield return new TileFrame { Tile = map.Tiles[f.GlobalTileId], Position_z = z };

                        // Next frames start off invisible / negative
                        sign = -1.0f;
                    }
                }
            }
        private PointF[] CalculateFaceTextureCoordinates(TmxTile tmxTile, bool flipDiagonal, bool flipHorizontal, bool flipVertical)
        {
            Point imageLocation = tmxTile.LocationOnSource;
            Size tileSize = tmxTile.TileSize;
            Size imageSize = tmxTile.TmxImage.Size;

            PointF[] points = new PointF[4];
            points[0] = imageLocation;
            points[1] = PointF.Add(imageLocation, new Size(tileSize.Width, 0));
            points[2] = PointF.Add(imageLocation, tileSize);
            points[3] = PointF.Add(imageLocation, new Size(0, tileSize.Height));

            PointF center = new PointF(tileSize.Width * 0.5f, tileSize.Height * 0.5f);
            center.X += imageLocation.X;
            center.Y += imageLocation.Y;
            TmxMath.TransformPoints_DiagFirst(points, center, flipDiagonal, flipHorizontal, flipVertical);
            //TmxMath.TransformPoints(points, center, flipDiagonal, flipHorizontal, flipVertical);

            PointF[] coordinates = new PointF[4];
            coordinates[3] = PointToTextureCoordinate(points[0], imageSize);
            coordinates[2] = PointToTextureCoordinate(points[1], imageSize);
            coordinates[1] = PointToTextureCoordinate(points[2], imageSize);
            coordinates[0] = PointToTextureCoordinate(points[3], imageSize);

            // Apply a small bias to the "inner" edges of the texels
            // This keeps us from seeing seams
            // (If seams continue along "outer" edges we can try applying the bias there as well)
            // Note: On Oct 25, a user was having issues with outer edges, so I brought those in as well afterall (for version 0.9.5.4)
            //const float bias = 1.0f / 8192.0f;
            //const float bias = 1.0f / 4096.0f;
            //const float bias = 1.0f / 2048.0f;
            float bias = 1.0f / Program.TexelBias;
            coordinates[0].X += bias;
            coordinates[0].Y += bias;

            coordinates[1].X -= bias;
            coordinates[1].Y += bias;

            coordinates[2].X -= bias;
            coordinates[2].Y -= bias;

            coordinates[3].X += bias;
            coordinates[3].Y -= bias;

            return coordinates;
        }
예제 #11
0
        // This method is called eventually for external tilesets too
        // Only the gid attribute has been consumed at this point for the tileset
        private void ParseInternalTileset(XElement elemTileset, uint firstId)
        {
            string tilesetName = TmxHelper.GetAttributeAsString(elemTileset, "name");

            Program.WriteLine("Parse internal tileset '{0}' (gid = {1}) ...", tilesetName, firstId);
            Program.WriteVerbose(elemTileset.ToString());

            int tileWidth = TmxHelper.GetAttributeAsInt(elemTileset, "tilewidth");
            int tileHeight = TmxHelper.GetAttributeAsInt(elemTileset, "tileheight");
            int spacing = TmxHelper.GetAttributeAsInt(elemTileset, "spacing", 0);
            int margin = TmxHelper.GetAttributeAsInt(elemTileset, "margin", 0);

            IList<TmxTile> tilesToAdd = new List<TmxTile>();

            // Tilesets may have an image for all tiles within it, or it may have an image per tile
            if (elemTileset.Element("image") != null)
            {
                TmxImage tmxImage = TmxImage.FromXml(elemTileset.Element("image"));
                RegisterImagePath(tmxImage.Path);

                // Create all the tiles
                // This is a bit complicated because of spacing and margin
                // (Margin is ignored from Width and Height)
                for (int end_y = margin + tileHeight; end_y <= tmxImage.Size.Height; end_y += spacing + tileHeight)
                {
                    for (int end_x = margin + tileWidth; end_x <= tmxImage.Size.Width; end_x += spacing + tileWidth)
                    {
                        uint localId = (uint) tilesToAdd.Count();
                        uint globalId = firstId + localId;
                        TmxTile tile = new TmxTile(globalId, localId, tilesetName, tmxImage);
                        tile.SetTileSize(tileWidth, tileHeight);
                        tile.SetLocationOnSource(end_x - tileWidth, end_y - tileHeight);
                        tilesToAdd.Add(tile);
                    }
                }
            }
            else
            {
                // Each tile will have it's own image
                foreach (var t in elemTileset.Elements("tile"))
                {
                    TmxImage tmxImage = TmxImage.FromXml(t.Element("image"));
                    RegisterImagePath(tmxImage.Path);

                    uint localId = (uint)tilesToAdd.Count();
                    uint globalId = firstId + localId;
                    TmxTile tile = new TmxTile(globalId, localId, tilesetName, tmxImage);
                    tile.SetTileSize(tmxImage.Size.Width, tmxImage.Size.Height);
                    tile.SetLocationOnSource(0, 0);
                    tilesToAdd.Add(tile);
                }
            }

            StringBuilder builder = new StringBuilder();
            foreach (TmxTile tile in tilesToAdd)
            {
                builder.AppendFormat("{0}", tile.ToString());
                if (tile != tilesToAdd.Last()) builder.Append("\n");
                this.Tiles[tile.GlobalId] = tile;
            }
            Program.WriteLine("Added {0} tiles", tilesToAdd.Count);
            Program.WriteVerbose(builder.ToString());

            // Add any extra data to tiles
            foreach (var elemTile in elemTileset.Elements("tile"))
            {
                int localTileId = TmxHelper.GetAttributeAsInt(elemTile, "id");
                var tiles = from t in this.Tiles
                            where t.Value.GlobalId == localTileId + firstId
                            select t.Value;
                tiles.First().ParseXml(elemTile, this, firstId);
            }
        }
예제 #12
0
        // Splits a layer into TmxMesh instances
        public static List <TmxMesh> ListFromTmxLayer(TmxLayer layer)
        {
            List <TmxMesh> meshes = new List <TmxMesh>();

            for (int i = 0; i < layer.TileIds.Count(); ++i)
            {
                // Copy the tile unto the mesh that uses the same image
                // (In other words, we are grouping tiles by images into a mesh)
                uint    tileId = layer.TileIds[i];
                TmxTile tile   = layer.TmxMap.GetTileFromTileId(tileId);
                if (tile == null)
                {
                    continue;
                }

                int timeMs = 0;
                foreach (var frame in tile.Animation.Frames)
                {
                    uint frameTileId = frame.GlobalTileId;

                    // Have to put any rotations/flipping from the source tile into this one
                    frameTileId |= (tileId & TmxMath.FLIPPED_HORIZONTALLY_FLAG);
                    frameTileId |= (tileId & TmxMath.FLIPPED_VERTICALLY_FLAG);
                    frameTileId |= (tileId & TmxMath.FLIPPED_DIAGONALLY_FLAG);

                    // Find a mesh to stick this tile into (if it exists)
                    TmxMesh mesh = meshes.Find(m => m.CanAddFrame(tile, timeMs, frame.DurationMs, tile.Animation.TotalTimeMs));
                    if (mesh == null)
                    {
                        var frameTile = layer.TmxMap.GetTileFromTileId(frameTileId);

                        // Create a new mesh and add it to our list
                        mesh                = new TmxMesh();
                        mesh.TileIds        = new uint[layer.TileIds.Count()];
                        mesh.UniqueMeshName = String.Format("mesh_{0}", layer.TmxMap.GetUniqueId().ToString("D4"));
                        mesh.TmxImage       = frameTile.TmxImage;

                        // Keep track of the timing for this mesh (non-animating meshes will have a start time and duration of 0)
                        mesh.StartTimeMs             = timeMs;
                        mesh.DurationMs              = frame.DurationMs;
                        mesh.FullAnimationDurationMs = tile.Animation.TotalTimeMs;
                        mesh.ObjectName              = Path.GetFileNameWithoutExtension(frameTile.TmxImage.AbsolutePath);

                        if (mesh.DurationMs != 0)
                        {
                            // Decorate the name a bit with some animation details for the frame
                            mesh.ObjectName += string.Format("[{0}-{1}][{2}]", timeMs, timeMs + mesh.DurationMs, mesh.FullAnimationDurationMs);
                        }

                        meshes.Add(mesh);
                    }

                    // This mesh contains this tile
                    mesh.AddTile(i, frameTileId);

                    // Advance time
                    timeMs += frame.DurationMs;
                }
            }

            return(meshes);
        }
예제 #13
0
        // This method is called eventually for external tilesets too
        // Only the gid attribute has been consumed at this point for the tileset
        private void ParseInternalTileset(XElement elemTileset, uint firstId)
        {
            string tilesetName = TmxHelper.GetAttributeAsString(elemTileset, "name");

            Program.WriteLine("Parse internal tileset '{0}' (gid = {1}) ...", tilesetName, firstId);
            Program.WriteVerbose(elemTileset.ToString());

            int tileWidth  = TmxHelper.GetAttributeAsInt(elemTileset, "tilewidth");
            int tileHeight = TmxHelper.GetAttributeAsInt(elemTileset, "tileheight");
            int spacing    = TmxHelper.GetAttributeAsInt(elemTileset, "spacing", 0);
            int margin     = TmxHelper.GetAttributeAsInt(elemTileset, "margin", 0);

            PointF   tileOffset    = PointF.Empty;
            XElement xmlTileOffset = elemTileset.Element("tileoffset");

            if (xmlTileOffset != null)
            {
                tileOffset.X = TmxHelper.GetAttributeAsInt(xmlTileOffset, "x");
                tileOffset.Y = TmxHelper.GetAttributeAsInt(xmlTileOffset, "y");
            }

            IList <TmxTile> tilesToAdd = new List <TmxTile>();

            // Tilesets may have an image for all tiles within it, or it may have an image per tile
            if (elemTileset.Element("image") != null)
            {
                TmxImage tmxImage = TmxImage.FromXml(elemTileset.Element("image"));

                // Create all the tiles
                // This is a bit complicated because of spacing and margin
                // (Margin is ignored from Width and Height)
                for (int end_y = margin + tileHeight; end_y <= tmxImage.Size.Height; end_y += spacing + tileHeight)
                {
                    for (int end_x = margin + tileWidth; end_x <= tmxImage.Size.Width; end_x += spacing + tileWidth)
                    {
                        uint    localId  = (uint)tilesToAdd.Count();
                        uint    globalId = firstId + localId;
                        TmxTile tile     = new TmxTile(globalId, localId, tilesetName, tmxImage);
                        tile.Offset = tileOffset;
                        tile.SetTileSize(tileWidth, tileHeight);
                        tile.SetLocationOnSource(end_x - tileWidth, end_y - tileHeight);
                        tilesToAdd.Add(tile);
                    }
                }
            }
            else
            {
                // Each tile will have it's own image
                foreach (var t in elemTileset.Elements("tile"))
                {
                    TmxImage tmxImage = TmxImage.FromXml(t.Element("image"));

                    uint    localId  = (uint)tilesToAdd.Count();
                    uint    globalId = firstId + localId;
                    TmxTile tile     = new TmxTile(globalId, localId, tilesetName, tmxImage);
                    tile.Offset = tileOffset;
                    tile.SetTileSize(tmxImage.Size.Width, tmxImage.Size.Height);
                    tile.SetLocationOnSource(0, 0);
                    tilesToAdd.Add(tile);
                }
            }

            StringBuilder builder = new StringBuilder();

            foreach (TmxTile tile in tilesToAdd)
            {
                builder.AppendFormat("{0}", tile.ToString());
                if (tile != tilesToAdd.Last())
                {
                    builder.Append("\n");
                }
                this.Tiles[tile.GlobalId] = tile;
            }
            Program.WriteLine("Added {0} tiles", tilesToAdd.Count);
            Program.WriteVerbose(builder.ToString());

            // Add any extra data to tiles
            foreach (var elemTile in elemTileset.Elements("tile"))
            {
                int localTileId = TmxHelper.GetAttributeAsInt(elemTile, "id");
                var tiles       = from t in this.Tiles
                                  where t.Value.GlobalId == localTileId + firstId
                                  select t.Value;
                tiles.First().ParseTileXml(elemTile, this, firstId);
            }
        }