Пример #1
0
        public Map Load(Stream stream)
        {
            ReadHeader(stream);

            MphdRecord mphdRecord = null;
            string[] authorLines = null;
            Color[] colourMap = null;
            BlockRecord[] blockRecords = null;
            AnimationRecord[] animationRecords = null;
            Image imageSource = null;
            short[][] layers = new short[8][];

            Dictionary<string, Chunk> chunks = MapChunks(stream);

            if (!chunks.ContainsKey("MPHD"))
                throw new Exception("Header chunk MPHD missing");
            Chunk mphdChunk = chunks["MPHD"];
            mphdRecord = ReadChunkMPHD(stream, mphdChunk);

            if (mphdRecord.BlockDepth == 8)
            {
                if (!chunks.ContainsKey("CMAP"))
                    throw new Exception("Colour map chuck CMAP is required for 8bit graphics blocks");
                Chunk cmapChunk = chunks["CMAP"];
                colourMap = ReadChunkCMAP(stream, cmapChunk);
            }

            if (chunks.ContainsKey("ATHR"))
                authorLines = ReadChunkATHR(stream, chunks["ATHR"]);

            if (!chunks.ContainsKey("BKDT"))
                throw new Exception("Block data chunk BKDT missing");
            Chunk bkdtChunk = chunks["BKDT"];
            blockRecords = ReadChunkBKDT(stream, bkdtChunk, mphdRecord);

            // optional ?
            if (chunks.ContainsKey("ANDT"))
            {
                Chunk andtChunk = chunks["ANDT"];
                animationRecords = ReadChunkANDT(stream, andtChunk, mphdRecord);
            }

            if (!chunks.ContainsKey("BGFX"))
                throw new Exception("Block graphics chunk BGFX missing");
            Chunk bgfxChunk = chunks["BGFX"];
            imageSource = ReadChunkBGFX(stream, bgfxChunk, mphdRecord, colourMap);

            if (!chunks.ContainsKey("BODY"))
                throw new Exception("Body chunk BODY missing");
            Chunk bodyChunk = chunks["BODY"];
            layers[0] = ReadChunkLayer(stream, bodyChunk, mphdRecord);

            // additional layers
            for (int layer = 1; layer <= 7; layer++)
            {
                string chunkId = "LYR" + layer;
                if (chunks.ContainsKey(chunkId))
                {
                    Chunk layerChuck = chunks[chunkId];
                    layers[layer] = ReadChunkLayer(stream, layerChuck, mphdRecord);
                }
            }

            // new map
            Map map = new Map();

            // attach ATHR lines as description
            if (authorLines != null)
            {
                StringBuilder stringBuilder = new StringBuilder();
                foreach (string authorLine in authorLines)
                    stringBuilder.AppendLine(authorLine);
                map.Description = stringBuilder.ToString();
            }

            // prompt user to save tilesheet image source
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.CheckPathExists = true;
            saveFileDialog.Filter = "Portable Network Geaphics (*.png)|*.png";
            saveFileDialog.OverwritePrompt = true;
            saveFileDialog.Title = "Save tile sheet image source as";
            saveFileDialog.ValidateNames = true;
            if (saveFileDialog.ShowDialog() == DialogResult.Cancel)
                throw new Exception("Mappy FMAP file import aborted");

            string tileSheetImageSource = saveFileDialog.FileName;

            imageSource.Save(tileSheetImageSource, ImageFormat.Png);

            // determine global tile size
            xTile.Dimensions.Size tileSize = new xTile.Dimensions.Size(mphdRecord.BlockWidth, mphdRecord.BlockHeight);

            // add tilesheet
            TileSheet tileSheet = new TileSheet("BGFX", map, tileSheetImageSource,
                new xTile.Dimensions.Size(1, mphdRecord.NumBlockGfx), tileSize);
            map.AddTileSheet(tileSheet);

            // determine global map size
            xTile.Dimensions.Size mapSize = new xTile.Dimensions.Size(mphdRecord.MapWidth, mphdRecord.MapHeight);

            // create layers
            for (int layerIndex = 0; layerIndex < 8; layerIndex++)
            {
                if (layers[layerIndex] == null)
                    continue;

                string layerId = layerIndex == 0 ? "BODY" : "LYR" + layerIndex;
                Layer layer = new Layer(layerId, map, mapSize, tileSize);
                map.AddLayer(layer);
                for (int tileY = 0; tileY < mapSize.Height; tileY++)
                {
                    for (int tileX = 0; tileX < mapSize.Width; tileX++)
                    {
                        int layerOffset = tileY * mapSize.Width + tileX;
                        int tileIndex = layers[layerIndex][layerOffset];
                        if (tileIndex >= 0)
                        {
                            layer.Tiles[tileX, tileY] = new StaticTile(layer, tileSheet, BlendMode.Alpha, tileIndex);
                        }
                        else
                        {
                            AnimationRecord animationRecord = animationRecords[-tileIndex - 1];
                            StaticTile[] tileFrames = new StaticTile[animationRecord.Frames.Length];

                            for (int frameIndex = 0; frameIndex < animationRecord.Frames.Length; frameIndex++)
                                tileFrames[frameIndex] = new StaticTile(layer, tileSheet, BlendMode.Alpha, animationRecord.Frames[frameIndex]);

                            // process loop types
                            switch (animationRecord.Type)
                            {
                                case 2: // LOOPR: loop backward
                                    Array.Reverse(tileFrames);
                                    break;
                                case 5: // PPFF -+
                                case 6: // PPRR  | - different states for ping-pong animation
                                case 7: // PPRF  | - treat all the same
                                case 8: // PPFR -+
                                    StaticTile[] pingPongFrames = new StaticTile[tileFrames.Length * 2 - 1];
                                    Array.Copy(tileFrames, pingPongFrames, tileFrames.Length);
                                    Array.Copy(tileFrames, 0, pingPongFrames, tileFrames.Length, tileFrames.Length - 1);
                                    Array.Reverse(pingPongFrames, tileFrames.Length, tileFrames.Length - 1);
                                    tileFrames = pingPongFrames;
                                    break;
                                default: // treat all other cases as LOOPF
                                    // 0 = NONE
                                    // 1 = LOOPF: loop forward
                                    // 3 = ONCE, 4 = ONCEH: one-off animations
                                    // 9 = ONCES: one-off animations
                                    break;
                            }

                            AnimatedTile animatedTile = new AnimatedTile(layer, tileFrames, (long)animationRecord.Delay * 20);
                            layer.Tiles[tileX, tileY] = animatedTile;
                        }
                    }
                }
            }

            return map;
        }
Пример #2
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);
        }
Пример #3
0
        public Map Load(Stream stream)
        {
            Map map = new Map("Flixel Map");

            // if using wait cursor, switch to default one during dialog
            bool useWaitCursor = Application.UseWaitCursor;
            Application.UseWaitCursor = false;
            Application.DoEvents();

            TileSheet tilesheet = new TileSheet("Flixel Tile Sheet", map, "", new Size(10, 10), new Size(16, 15));
            TileSheetPropertiesDialog tileSheetPropertiesDialog = new TileSheetPropertiesDialog(tilesheet, true, null);
            if (tileSheetPropertiesDialog.ShowDialog() == DialogResult.Cancel)
                throw new Exception("No tile sheet configured");

            Application.UseWaitCursor = useWaitCursor;
            Application.DoEvents();

            TextReader layerTextReader = new StreamReader(stream);

            List<List<int>> tileIndices = new List<List<int>>();

            char[] commas = new char[] { ',' };
            Size layerSize = new Size();

            while (true)
            {
                string layerLine = layerTextReader.ReadLine();
                if (layerLine == null)
                    break;

                List<int> indexRow = new List<int>();
                tileIndices.Add(indexRow);

                string[] tokens = layerLine.Split(commas);

                layerSize.Width = Math.Max(layerSize.Width, tokens.Length);

                foreach (string token in tokens)
                {
                    int tileIndex = int.Parse(token.Trim());
                    indexRow.Add(tileIndex);
                }

                layerSize.Height++;
            }

            Layer layer = new Layer("Flixel Layer", map, layerSize, tilesheet.TileSize);
            map.AddLayer(layer);

            for (int tileY = 0; tileY < tileIndices.Count; tileY++)
            {
                List<int> indexRow = tileIndices[tileY];
                for (int tileX = 0; tileX < indexRow.Count; tileX++)
                    layer.Tiles[tileX, tileY] = new StaticTile(layer, tilesheet, BlendMode.Alpha, indexRow[tileX]);
            }

            return map;
        }
Пример #4
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);
        }