Пример #1
0
        public Map Load(System.IO.Stream stream)
        {
            XmlTextReader xmlReader = new XmlTextReader(stream);
            xmlReader.WhitespaceHandling = WhitespaceHandling.None;

            XmlHelper xmlHelper = new XmlHelper(xmlReader);

            xmlHelper.AdvanceDeclaration();
            xmlHelper.AdvanceStartElement("Map");
            string mapId = xmlHelper.GetAttribute("Id");
            Map map = new Map(mapId);

            xmlHelper.AdvanceStartElement("Description");
            string mapDescription = xmlHelper.GetCData();
            xmlHelper.AdvanceEndElement("Description");
            map.Description = mapDescription;

            LoadTileSheets(xmlHelper, map);

            LoadLayers(xmlHelper, map);

            LoadProperties(xmlHelper, map);

            return map;
        }
Пример #2
0
        private void LoadTileSheets(XmlHelper xmlHelper, Map map)
        {
            xmlHelper.AdvanceStartElement("TileSheets");

            while (xmlHelper.AdvanceStartRepeatedElement("TileSheet", "TileSheets"))
                LoadTileSheet(xmlHelper, map);
        }
Пример #3
0
        private void LoadTileSheet(XmlHelper xmlHelper, Map map)
        {
            string id = xmlHelper.GetAttribute("Id");

            xmlHelper.AdvanceStartElement("Description");
            string description = xmlHelper.GetCData();
            xmlHelper.AdvanceEndElement("Description");

            xmlHelper.AdvanceStartElement("ImageSource");
            string imageSource = xmlHelper.GetCData();
            xmlHelper.AdvanceEndElement("ImageSource");

            xmlHelper.AdvanceStartElement("Alignment");

            Size sheetSize = Size.FromString(xmlHelper.GetAttribute("SheetSize"));
            Size tileSize = Size.FromString(xmlHelper.GetAttribute("TileSize"));
            Size margin = Size.FromString(xmlHelper.GetAttribute("Margin"));
            Size spacing = Size.FromString(xmlHelper.GetAttribute("Spacing"));

            xmlHelper.AdvanceEndElement("Alignment");

            TileSheet tileSheet = new TileSheet(id, map, imageSource, sheetSize, tileSize);
            tileSheet.Margin = margin;
            tileSheet.Spacing = spacing;

            LoadProperties(xmlHelper, tileSheet);

            xmlHelper.AdvanceEndElement("TileSheet");

            map.AddTileSheet(tileSheet);
        }
Пример #4
0
        private StaticTile LoadStaticTile(XmlHelper xmlHelper, Layer layer, TileSheet tileSheet)
        {
            int tileIndex = xmlHelper.GetIntAttribute("Index");
            BlendMode blendMode
                = xmlHelper.GetAttribute("BlendMode") == BlendMode.Alpha.ToString()
                    ? BlendMode.Alpha : BlendMode.Additive;

            StaticTile staticTile = new StaticTile(layer, tileSheet, blendMode, tileIndex);

            if (!xmlHelper.XmlReader.IsEmptyElement)
            {
                LoadProperties(xmlHelper, staticTile);
                xmlHelper.AdvanceEndElement("Static");
            }

            return staticTile;
        }
Пример #5
0
        private void LoadProperties(XmlHelper xmlHelper, Component component)
        {
            xmlHelper.AdvanceStartElement("Properties");

            while (xmlHelper.AdvanceStartRepeatedElement("Property", "Properties"))
            {
                string propertyKey = xmlHelper.GetAttribute("Key");
                string propertyType = xmlHelper.GetAttribute("Type");
                string propertyValue = xmlHelper.GetCData();

                if (propertyType == typeof(bool).Name)
                    component.Properties[propertyKey] = bool.Parse(propertyValue);
                else if (propertyType == typeof(int).Name)
                    component.Properties[propertyKey] = int.Parse(propertyValue);
                else if (propertyType == typeof(float).Name)
                    component.Properties[propertyKey] = float.Parse(propertyValue);
                else
                    component.Properties[propertyKey] = propertyValue;

                xmlHelper.AdvanceEndElement("Property");
            }
        }
Пример #6
0
        private void LoadLayers(XmlHelper xmlHelper, Map map)
        {
            xmlHelper.AdvanceStartElement("Layers");

            while (xmlHelper.AdvanceStartRepeatedElement("Layer", "Layers"))
                LoadLayer(xmlHelper, map);
        }
Пример #7
0
        private void LoadLayer(XmlHelper xmlHelper, Map map)
        {
            string id = xmlHelper.GetAttribute("Id");

            bool visible = bool.Parse(xmlHelper.GetAttribute("Visible"));

            xmlHelper.AdvanceStartElement("Description");
            string description = xmlHelper.GetCData();
            xmlHelper.AdvanceEndElement("Description");

            xmlHelper.AdvanceStartElement("Dimensions");
            Size layerSize = Size.FromString(xmlHelper.GetAttribute("LayerSize"));
            Size tileSize = Size.FromString(xmlHelper.GetAttribute("TileSize"));
            xmlHelper.AdvanceEndElement("Dimensions");

            Layer layer = new Layer(id, map, layerSize, tileSize);
            layer.Description = description;
            layer.Visible = visible;

            xmlHelper.AdvanceStartElement("TileArray");

            Location tileLocation = Location.Origin;
            TileSheet tileSheet = null;
            XmlReader xmlReader = xmlHelper.XmlReader;
            while (xmlHelper.AdvanceStartRepeatedElement("Row", "TileArray"))
            {
                tileLocation.X = 0;

                while (xmlHelper.AdvanceNode() != XmlNodeType.EndElement)
                {
                    if (xmlReader.Name == "Null")
                    {
                        int nullCount = xmlHelper.GetIntAttribute("Count");
                        tileLocation.X += nullCount % layerSize.Width;
                    }
                    else if (xmlReader.Name == "TileSheet")
                    {
                        string tileSheetRef = xmlHelper.GetAttribute("Ref");
                        tileSheet = map.GetTileSheet(tileSheetRef);
                    }
                    else if (xmlReader.Name == "Static")
                    {
                        layer.Tiles[tileLocation] = LoadStaticTile(xmlHelper, layer, tileSheet);

                        ++tileLocation.X;
                    }
                    else if (xmlReader.Name == "Animated")
                    {
                        layer.Tiles[tileLocation] = LoadAnimatedTile(xmlHelper, layer, tileSheet);

                        ++tileLocation.X;
                    }
                }

                ++tileLocation.Y;
            }

            LoadProperties(xmlHelper, layer);

            xmlHelper.AdvanceEndElement("Layer");

            map.AddLayer(layer);
        }
Пример #8
0
        private AnimatedTile LoadAnimatedTile(XmlHelper xmlHelper, Layer layer, TileSheet tileSheet)
        {
            int frameInterval = xmlHelper.GetIntAttribute("Interval");

            xmlHelper.AdvanceStartElement("Frames");

            Map map = layer.Map;
            List<StaticTile> tileFrames = new List<StaticTile>();

            while (xmlHelper.AdvanceNode() != XmlNodeType.EndElement)
            {
                if (xmlHelper.XmlReader.Name == "Static")
                    tileFrames.Add(LoadStaticTile(xmlHelper, layer, tileSheet));
                else if (xmlHelper.XmlReader.Name == "TileSheet")
                {
                    string tileSheetRef = xmlHelper.GetAttribute("Ref");
                    tileSheet = map.GetTileSheet(tileSheetRef);
                }
            }

            AnimatedTile animatedTile
                = new AnimatedTile(layer, tileFrames.ToArray(), frameInterval);

            // end of this element or optional props
            if (xmlHelper.AdvanceNode() != XmlNodeType.EndElement)
                LoadProperties(xmlHelper, animatedTile);

            return animatedTile;
        }
Пример #9
0
        private void LoadTileSet(XmlHelper xmlHelper, Map map)
        {
            string id = xmlHelper.GetAttribute("name");

            int firstGid = xmlHelper.GetIntAttribute("firstgid");

            int tileWidth = xmlHelper.GetIntAttribute("tilewidth");
            int tileHeight = xmlHelper.GetIntAttribute("tileheight");
            Size tileSize = new Size(tileWidth, tileHeight);

            int marginValue = xmlHelper.GetIntAttribute("margin", 0);
            Size margin = new Size(marginValue);

            int spacingValue = xmlHelper.GetIntAttribute("spacing", 0);
            Size spacing = new Size(spacingValue);

            xmlHelper.AdvanceStartElement("image");
            string imageSource = xmlHelper.GetAttribute("source");
            xmlHelper.AdvanceEndElement("image");

            Size sheetSize = new Size();
            try
            {
                using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(imageSource))
                {
                    sheetSize.Width = (bitmap.Width + spacingValue - marginValue) / (tileWidth + spacingValue);
                    sheetSize.Height = (bitmap.Height + spacingValue - marginValue) / (tileHeight + spacingValue);
                }
            }
            catch (Exception exception)
            {
                throw new Exception("Unable to determine sheet size from image source", exception);
            }

            TileSheet tileSheet = new TileSheet(id, map, imageSource, sheetSize, tileSize);
            tileSheet.Margin = margin;
            tileSheet.Spacing = spacing;

            // keep track of first gid as custom property
            tileSheet.Properties["@FirstGid"] = firstGid;

            // also add lastgid to facilitate import
            tileSheet.Properties["@LastGid"] = firstGid + tileSheet.TileCount - 1;

            // properties at tile level within tile sets not supported
            // but are mapped as prefixed properties at tile sheet level
            XmlNodeType xmlNodeType = xmlHelper.AdvanceNode();
            while (xmlNodeType == XmlNodeType.Element && xmlHelper.XmlReader.Name == "tile")
            {
                int tileId = xmlHelper.GetIntAttribute("id");
                xmlHelper.AdvanceNamedNode(XmlNodeType.Element, "properties");
                Component dummyComponent = new DummyComponent();
                LoadProperties(xmlHelper, dummyComponent);
                xmlHelper.AdvanceEndElement("tile");

                foreach (string propertyName in dummyComponent.Properties.Keys)
                {
                    tileSheet.Properties["@Tile@" + tileId + "@" + propertyName]
                        = dummyComponent.Properties[propertyName];
                }

                xmlNodeType = xmlHelper.AdvanceNode();
            }

            map.AddTileSheet(tileSheet);
        }
Пример #10
0
        private void LoadProperties(XmlHelper xmlHelper, Component component)
        {
            while (xmlHelper.AdvanceStartRepeatedElement("property", "properties"))
            {
                string propertyKey = xmlHelper.GetAttribute("name");
                string propertyValue = xmlHelper.GetAttribute("value");

                component.Properties[propertyKey] = propertyValue;

                xmlHelper.AdvanceEndElement("property");
            }
        }
Пример #11
0
        private void LoadLayerDataXml(XmlHelper xmlHelper, Layer layer)
        {
            Location tileLocation = Location.Origin;

            while (xmlHelper.AdvanceStartRepeatedElement("tile", "data"))
            {
                int gid = xmlHelper.GetIntAttribute("gid");

                layer.Tiles[tileLocation] = LoadStaticTile(layer, gid);

                ++tileLocation.X;
                if (tileLocation.X >= layer.LayerWidth)
                {
                    tileLocation.X = 0;
                    ++tileLocation.Y;
                }
            }
        }
Пример #12
0
        private void LoadLayerDataCsv(XmlHelper xmlHelper, Layer layer)
        {
            xmlHelper.AdvanceNode(XmlNodeType.Text);

            XmlReader xmlReader = xmlHelper.XmlReader;

            string csvData = xmlReader.Value;
            string[] csvElements = csvData.Split(new char[] { ',', '\r', '\n', '\t' }, StringSplitOptions.RemoveEmptyEntries);

            Location tileLocation = Location.Origin;
            foreach (string csvElement in csvElements)
            {
                int gid = int.Parse(csvElement);

                layer.Tiles[tileLocation] = LoadStaticTile(layer, gid);

                ++tileLocation.X;
                if (tileLocation.X >= layer.LayerWidth)
                {
                    tileLocation.X = 0;
                    ++tileLocation.Y;
                }
            }

            xmlHelper.AdvanceEndElement("data");
        }
Пример #13
0
        private void LoadLayerDataBase64(XmlHelper xmlHelper, Layer layer, string dataCompression)
        {
            xmlHelper.AdvanceNode(XmlNodeType.Text);

            string base64Data = xmlHelper.XmlReader.Value;

            byte[] dataBytes = System.Convert.FromBase64String(base64Data);

            if (dataCompression == "none")
            {
                // do nothing
            }
            else if (dataCompression == "gzip")
            {
                GZipStream inGZipStream = new GZipStream(
                    new MemoryStream(dataBytes), CompressionMode.Decompress);

                MemoryStream outMemoryStream = new MemoryStream();

                byte[] buffer = new byte[1024];
                while (true)
                {
                    int bytesRead = inGZipStream.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                        break;
                    outMemoryStream.Write(buffer, 0, bytesRead);
                }

                dataBytes = outMemoryStream.ToArray();
            }
            else if (dataCompression == "zlib")
            {
                ZInputStream inZInputStream = new ZInputStream(
                    new MemoryStream(dataBytes));

                MemoryStream outMemoryStream = new MemoryStream();

                byte[] buffer = new byte[1024];
                while (true)
                {
                    int bytesRead = inZInputStream.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                        break;
                    outMemoryStream.Write(buffer, 0, bytesRead);
                }

                dataBytes = outMemoryStream.ToArray();
            }
            else
                throw new Exception("Unknown compression scheme: " + dataCompression);

            if (dataBytes.Length % 4 != 0)
                throw new Exception("Base64 byte stream size must be a mutliple of 4 bytes");

            Location tileLocation = Location.Origin;
            for (int byteIndex = 0; byteIndex < dataBytes.Length; byteIndex += 4)
            {
                int gid =
                    dataBytes[byteIndex] |
                    dataBytes[byteIndex + 1] << 8 |
                    dataBytes[byteIndex + 2] << 16 |
                    dataBytes[byteIndex + 3] << 24;

                layer.Tiles[tileLocation] = LoadStaticTile(layer, gid);

                ++tileLocation.X;
                if (tileLocation.X >= layer.LayerWidth)
                {
                    tileLocation.X = 0;
                    ++tileLocation.Y;
                }
            }

            xmlHelper.AdvanceEndElement("data");
        }
Пример #14
0
        private void LoadLayer(XmlHelper xmlHelper, Map map)
        {
            if (map.TileSheets.Count == 0)
                throw new Exception("Must load at least one tileset to determine layer tile size");

            string id = xmlHelper.GetAttribute("name");

            int layerWidth = xmlHelper.GetIntAttribute("width");
            int layerHeight = xmlHelper.GetIntAttribute("height");
            Size layerSize = new Size(layerWidth, layerHeight);

            int visible = xmlHelper.GetIntAttribute("visible", 1);

            // must assume tile size from first tile set
            Size tileSize = map.TileSheets[0].TileSize;

            Layer layer = new Layer(id, map, layerSize, tileSize);
            layer.Visible = visible > 0;

            // load properties if available
            XmlNodeType xmlNodeType = xmlHelper.AdvanceNode();
            if (xmlNodeType == XmlNodeType.Element && xmlHelper.XmlReader.Name == "properties")
            {
                LoadProperties(xmlHelper, layer);

                // try to obtain layer description via custom property
                if (layer.Properties.ContainsKey("@Description"))
                    layer.Description = layer.Properties["@Description"];

                xmlHelper.AdvanceStartElement("data");
            }
            else if (xmlNodeType != XmlNodeType.Element || xmlHelper.XmlReader.Name != "data")
                throw new Exception("The element <properties> or <data> expected");

            string dataEncoding = xmlHelper.GetAttribute("encoding", "xml");
            string dataCompression = xmlHelper.GetAttribute("compression", "none");

            if (dataEncoding == "xml")
                LoadLayerDataXml(xmlHelper, layer);
            else if (dataEncoding == "base64")
                LoadLayerDataBase64(xmlHelper, layer, dataCompression);
            else if (dataEncoding == "csv")
                LoadLayerDataCsv(xmlHelper, layer);
            else
                throw new Exception("Unknown encoding/compression setting combination (" + dataEncoding + "/" + dataCompression + ")");

            xmlHelper.AdvanceEndElement("layer");

            map.AddLayer(layer);
        }
Пример #15
0
        public Map Load(Stream stream)
        {
            XmlTextReader xmlReader = new XmlTextReader(stream);
            xmlReader.WhitespaceHandling = WhitespaceHandling.None;

            XmlHelper xmlHelper = new XmlHelper(xmlReader);

            xmlHelper.AdvanceDeclaration();
            xmlHelper.AdvanceStartElement("map");

            string orientation = xmlHelper.GetAttribute("orientation");

            if (orientation != "orthogonal")
                throw new Exception("Only orthogonal Tiled maps are supported.");

            int mapWidth = xmlHelper.GetIntAttribute("width");
            int mapHeight = xmlHelper.GetIntAttribute("height");

            int tileWidth = xmlHelper.GetIntAttribute("tilewidth");
            int tileHeight = xmlHelper.GetIntAttribute("tileheight");

            Map map = new Map();

            while (true)
            {
                XmlNodeType xmlNodeType = xmlHelper.AdvanceNode();
                if (xmlNodeType == XmlNodeType.EndElement)
                    break;

                if (xmlReader.Name == "properties")
                    LoadProperties(xmlHelper, map);
                else if (xmlReader.Name == "tileset")
                    LoadTileSet(xmlHelper, map);
                else if (xmlReader.Name == "layer")
                    LoadLayer(xmlHelper, map);
                else
                    xmlHelper.SkipToEndElement(xmlReader.Name);
            }

            // try to obtain map description via custom property
            if (map.Properties.ContainsKey("@Description"))
                map.Description = map.Properties["@Description"];

            return map;
        }
Пример #16
0
        private void LoadLayer(XmlHelper xmlHelper, Map map)
        {
            string id = xmlHelper.GetAttribute("Id");

            bool visible = bool.Parse(xmlHelper.GetAttribute("Visible"));

            xmlHelper.AdvanceStartElement("Description");
            string description = xmlHelper.GetCData();
            xmlHelper.AdvanceEndElement("Description");

            xmlHelper.AdvanceStartElement("Dimensions");
            Size layerSize = Size.FromString(xmlHelper.GetAttribute("LayerSize"));
            Size tileSize = Size.FromString(xmlHelper.GetAttribute("TileSize"));
            xmlHelper.AdvanceEndElement("Dimensions");

            Layer layer = new Layer(id, map, layerSize, tileSize);
            layer.Description = description;
            layer.Visible = visible;

            xmlHelper.AdvanceStartElement("TileData");
            string tileSheetId = xmlHelper.GetAttribute("TileSheet");
            string layerFilename = xmlHelper.GetAttribute("Filename");
            xmlHelper.AdvanceEndElement("TileData");

            TileSheet tileSheet = map.GetTileSheet(tileSheetId);
            if (tileSheet == null)
                throw new Exception("Invalid tile sheet reference: " + tileSheetId);

            TextReader layerTextReader = new StreamReader(layerFilename);
            int tileY = 0;
            char[] commas = new char[]{','};
            while (tileY < layer.LayerHeight)
            {
                string layerLine = layerTextReader.ReadLine();
                if (layerLine == null)
                    break;

                string[] tokens = layerLine.Split(commas);
                int tileX = 0;
                foreach (string token in tokens)
                {
                    if (tileX >= layer.LayerWidth)
                        break;
                    int tileIndex = int.Parse(token.Trim());
                    layer.Tiles[tileX++, tileY] = new StaticTile(layer, tileSheet, BlendMode.Alpha, tileIndex);
                }

                ++tileY;
            }
            layerTextReader.Close();

            LoadProperties(xmlHelper, layer);

            xmlHelper.AdvanceEndElement("Layer");

            map.AddLayer(layer);
        }