private void AddTileFrame(StaticTile newTileFrame) { if (m_imageListAnimation.Images.Count == 0) { m_imageListAnimation.ImageSize = new System.Drawing.Size( newTileFrame.TileSheet.TileWidth, newTileFrame.TileSheet.TileHeight); } // determine or add new image index int imageListIndex = -1; foreach (ListViewItem listViewItem in m_animationListView.Items) { StaticTile tileFrame = (StaticTile)listViewItem.Tag; if (tileFrame.TileSheet == newTileFrame.TileSheet && tileFrame.TileIndex == newTileFrame.TileIndex) { imageListIndex = listViewItem.ImageIndex; break; } } if (imageListIndex == -1) { Image tileImage = TileImageCache.Instance.GetTileBitmap(newTileFrame.TileSheet, newTileFrame.TileIndex); m_imageListAnimation.Images.Add(tileImage); imageListIndex = m_imageListAnimation.Images.Count - 1; } ListViewItem newListViewItem = new ListViewItem( "Frame #" + m_animationListView.Items.Count, imageListIndex); newListViewItem.Tag = newTileFrame; m_animationListView.Items.Add(newListViewItem); }
public override void Do() { m_oldFringeAssignments.Clear(); Size blockSize = new Size(m_oldTiles.GetLength(0), m_oldTiles.GetLength(1)); int tileY = m_blockLocation.Y; for (int blockY = 0; blockY < blockSize.Height; blockY++, tileY++) { int tileX = m_blockLocation.X; for (int blockX = 0; blockX < blockSize.Width; blockX++, tileX++) { // place block tile (after preserving old tile) m_oldTiles[blockX, blockY] = m_layer.Tiles[tileX, tileY]; StaticTile localTile = new StaticTile(m_layer, m_tileSheet, BlendMode.Alpha, m_tileIndex); m_layer.Tiles[tileX, tileY] = localTile; // determine local fringe auto-tiles Dictionary<Location, Tile> localAssignments = AutoTileManager.Instance.DetermineTileAssignments( m_layer, new Location(tileX, tileY), localTile); // place fringe auto-tiles (after preserving previous tiles) foreach (Location locationKey in localAssignments.Keys) { m_oldFringeAssignments[locationKey] = m_layer.Tiles[locationKey]; m_layer.Tiles[locationKey] = localAssignments[locationKey]; } } } }
/// <summary> /// Constructs a new animated tile for the given layer, using the /// given tile frames and frame interval /// </summary> /// <param name="layer">Layer to assign the tile to</param> /// <param name="tileFrames">Array of StaticTile instances</param> /// <param name="frameInterval">Frame interval in milliseconds</param> public AnimatedTile(Layer layer, StaticTile[] tileFrames, long frameInterval) : base(layer) { if (frameInterval <= 0) throw new Exception("Frame interval must be strictly positive"); m_tileFrames = new StaticTile[tileFrames.Length]; tileFrames.CopyTo(m_tileFrames, 0); m_frameInterval = frameInterval; m_animationInterval = frameInterval * tileFrames.Length; }
public Dictionary<Location, Tile> DetermineTileAssignments(Layer layer, Location tileLocation, StaticTile staticTile) { Dictionary<Location, Tile> allAssignments = new Dictionary<Location, Tile>(); foreach (AutoTile autoTile in m_autoTiles) { if (autoTile.TileSheet != staticTile.TileSheet) continue; Dictionary<Location, Tile> assignments = autoTile.DetermineTileAssignments(layer, tileLocation, staticTile.TileIndex); foreach (Location location in assignments.Keys) allAssignments[location] = assignments[location]; } if (m_autoTiles.Count == 0) allAssignments[tileLocation] = staticTile.Clone(layer); return allAssignments; }
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 AddTileFrame(TileSheet tileSheet, int tileIndex) { StaticTile newTileFrame = new StaticTile(m_layer, tileSheet, BlendMode.Alpha, tileIndex); AddTileFrame(newTileFrame); }
private void StoreStaticTile(Stream stream, StaticTile staticTile) { StoreInt32(stream, staticTile.TileIndex); stream.WriteByte((byte)staticTile.BlendMode); StoreProperties(stream, staticTile); }
private StaticTile LoadStaticTile(Stream stream, Layer layer, TileSheet tileSheet) { int tileIndex = LoadInt32(stream); BlendMode blendMode = (BlendMode)stream.ReadByte(); StaticTile staticTile = new StaticTile(layer, tileSheet, blendMode, tileIndex); LoadProperties(stream, staticTile); return staticTile; }
public Dictionary<Location, Tile> DetermineTileAssignments(Layer layer, Location tileLocation, int tileIndex) { // prepare blank assignment lists Dictionary<Location, Tile> autoTileAssignments = new Dictionary<Location, Tile>(); // validate centre tile location if (!layer.IsValidTileLocation(tileLocation)) return autoTileAssignments; // get and validate set index within auto tile definition int centreIndex = GetSetIndex(tileIndex); if (centreIndex == -1) return autoTileAssignments; // add centre tile Tile oldCentreTile = layer.Tiles[tileLocation]; if (oldCentreTile == null || oldCentreTile.TileSheet != m_tileSheet || oldCentreTile.TileIndex != tileIndex) { Tile centreTile = new StaticTile(layer, m_tileSheet, BlendMode.Alpha, tileIndex); autoTileAssignments[tileLocation] = centreTile; } // determine and add adjacent tiles where applicable // top left Location topLeft = tileLocation.AboveLeft; Tile topLeftTile = DetermineAdjacentTile(layer, centreIndex, topLeft, new int[] { 0 }, new int[] { 3 }); if (topLeftTile != null) autoTileAssignments[topLeft]= topLeftTile; // top Location top = tileLocation.Above; Tile topTile = DetermineAdjacentTile(layer, centreIndex, top, new int[] { 0, 1 }, new int[] { 2, 3 }); if (topTile != null) autoTileAssignments[top]= topTile; // top right Location topRight = tileLocation.AboveRight; Tile topRightTile = DetermineAdjacentTile(layer, centreIndex, topRight, new int[] { 1 }, new int[] { 2 }); if (topRightTile != null) autoTileAssignments[topRight] = topRightTile; // left Location left = tileLocation.Left; Tile leftTile = DetermineAdjacentTile(layer, centreIndex, left, new int[] { 0, 2 }, new int[] { 1, 3 }); if (leftTile != null) autoTileAssignments[left] = leftTile; // right Location right = tileLocation.Right; Tile rightTile = DetermineAdjacentTile(layer, centreIndex, right, new int[] { 1, 3 }, new int[] { 0, 2 }); if (rightTile != null) autoTileAssignments[right] = rightTile; // bottom left Location bottomLeft = tileLocation.BelowLeft; Tile bottomLeftTile = DetermineAdjacentTile(layer, centreIndex, bottomLeft, new int[] { 2 }, new int[] { 1 }); if (bottomLeftTile != null) autoTileAssignments[bottomLeft] = bottomLeftTile; // bottom Location bottom = tileLocation.Below; Tile bottomTile = DetermineAdjacentTile(layer, centreIndex, bottom, new int[] { 2, 3 }, new int[] { 0, 1 }); if (bottomTile != null) autoTileAssignments[bottom] = bottomTile; // bottom right Location bottomRight = tileLocation.BelowRight; Tile bottomRightTile = DetermineAdjacentTile(layer, centreIndex, bottomRight, new int[] { 3 }, new int[] { 0 }); if (bottomRightTile != null) autoTileAssignments[bottomRight] = bottomRightTile; return autoTileAssignments; }
private void StoreStaticTile(StaticTile staticTile, XmlWriter xmlWriter) { xmlWriter.WriteStartElement("Static"); xmlWriter.WriteAttributeString("Index", staticTile.TileIndex.ToString()); xmlWriter.WriteAttributeString("BlendMode", staticTile.BlendMode.ToString()); if (staticTile.Properties.Count > 0) StoreProperties(staticTile, xmlWriter); xmlWriter.WriteEndElement(); }
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; }
/// <summary> /// Clones the tile for the given Layer /// </summary> /// <param name="layer">Layer to assigned to the cloned tile</param> /// <returns>Cloned static tile</returns> public override Tile Clone(Layer layer) { Tile tileClone = new StaticTile(layer, this.TileSheet, this.BlendMode, m_tileIndex); tileClone.Properties.CopyFrom(Properties); return tileClone; }