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; }
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); }
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; }
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); }