Beispiel #1
0
        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);
        }
Beispiel #2
0
        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];
                    }
                }
            }
        }
Beispiel #3
0
        /// <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;
        }
Beispiel #4
0
        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;
        }
Beispiel #5
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;
        }
Beispiel #6
0
 private void AddTileFrame(TileSheet tileSheet, int tileIndex)
 {
     StaticTile newTileFrame = new StaticTile(m_layer, tileSheet, BlendMode.Alpha, tileIndex);
     AddTileFrame(newTileFrame);
 }
Beispiel #7
0
 private void StoreStaticTile(Stream stream, StaticTile staticTile)
 {
     StoreInt32(stream, staticTile.TileIndex);
     stream.WriteByte((byte)staticTile.BlendMode);
     StoreProperties(stream, staticTile);
 }
Beispiel #8
0
 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;
 }
Beispiel #9
0
        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;
        }
Beispiel #10
0
        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();
        }
Beispiel #11
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;
        }
Beispiel #12
0
 /// <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;
 }