private void Redraw()
        {
            if (this.disableRedrawing)
            {
                return;
            }

            var selectedSpec    = this.config.GetSpecById((int)this.tilesetComboBox.SelectedItem);
            var selectedPalette = this.palettes.BackgroundPalettes.First(p => p.Id == (int)this.paletteComboBox.SelectedItem);

            var bgSpec      = selectedSpec.GetBgSpec();
            var blocking    = MyBitmap.FromFile(bgSpec.BlockingFile).Scale(2);
            var nonBlocking = MyBitmap.FromFile(bgSpec.NonBlockingFile).Scale(2);
            var threats     = MyBitmap.FromFile(bgSpec.ThreatFile).Scale(2);

            var packed = Packer.Pack(new Size[] { blocking.Size, nonBlocking.Size, threats.Size }, maxWidth);

            var width  = packed.Max(tpl => tpl.Item1.X + tpl.Item2.Width);
            var height = packed.Max(tpl => tpl.Item1.Y + tpl.Item2.Height);

            var blockingPosition = packed.First(tpl => tpl.Item2 == blocking.Size);

            packed.Remove(blockingPosition);
            var nonBlockingPosition = packed.First(tpl => tpl.Item2 == nonBlocking.Size);

            packed.Remove(nonBlockingPosition);
            var threatsPosition = packed.First(); // only one left

            var palette = this.palettes.BackgroundPalettes[this.SelectedPalette];
            var bgColor = palette.Palettes.First().ActualColors.First();

            var bigBitmap = new MyBitmap(2 * width + 30, 2 * height + 30, bgColor);

            for (var i = 0; i <= 3; i++)
            {
                var bitmap = new MyBitmap(width, height, bgColor);

                var blockingClone = blocking.Clone();
                blockingClone.UpdateColors(blockingClone.UniqueColors(), palette.Palettes[i].ActualColors);
                var nonBlockingClone = nonBlocking.Clone();
                nonBlockingClone.UpdateColors(nonBlockingClone.UniqueColors(), palette.Palettes[i].ActualColors);
                var threatsClone = threats.Clone();
                threatsClone.UpdateColors(threatsClone.UniqueColors(), palette.Palettes[i].ActualColors);

                bitmap.DrawImage(blockingClone, blockingPosition.Item1.X, blockingPosition.Item1.Y);
                bitmap.DrawImage(nonBlockingClone, nonBlockingPosition.Item1.X, nonBlockingPosition.Item1.Y);
                bitmap.DrawImage(threatsClone, threatsPosition.Item1.X, threatsPosition.Item1.Y);

                bigBitmap.DrawImage(bitmap, 10 + (i % 2) * (bitmap.Width + 10), 10 + (i / 2) * (bitmap.Height + 10));
            }

            this.pictureBox.Image = bigBitmap.ToBitmap();

            var newWidth  = Math.Max(bigBitmap.Width, minWidth);
            var newHeight = bigBitmap.Height + heightOffset;

            this.Width  = newWidth + widthOffset;
            this.Height = Math.Min(newHeight, maxHeight);
            this.Refresh();
        }
        private Bitmap DrawBullet(Bitmap image, Animation animation, bool flip, int zoom)
        {
            var width  = image.Width;
            var height = image.Height;

            var xOff = Constants.SpriteWidth * zoom;
            var yOff = Constants.SpriteHeight * zoom;

            var newImage = new MyBitmap(width + xOff * 2, height + yOff * 2, this.pictureBox.BackColor);

            newImage.DrawImage(MyBitmap.FromBitmap(image), xOff, yOff);

            if (animation.Offsets.GunXOff >= 0)
            {
                var bullet       = this.bulletConfig.Bullets.First(b => b.BulletId == animation.BulletId);
                var flipFlags    = bullet.GetFlipFlags(flip);
                var bulletBitmap = bullet.Sprite.GetSprite(
                    this.applyPaletteCheckbox.Checked,
                    flipFlags.HasFlag(ImageFlags.VFlip),
                    flipFlags.HasFlag(ImageFlags.HFlip),
                    this.pictureBox.BackColor).Clone();

                var scaled = bulletBitmap.Scale(zoom);
                if (flip)
                {
                    newImage.DrawImage(
                        scaled,
                        xOff + animation.Offsets.GunXOffFlip * zoom,
                        yOff + animation.Offsets.GunYOffFlip * zoom);
                }
                else
                {
                    newImage.DrawImage(
                        scaled,
                        xOff + animation.Offsets.GunXOff * zoom,
                        yOff + animation.Offsets.GunYOff * zoom);
                }
            }


            return(newImage.ToBitmap());
        }
Exemple #3
0
        private MyBitmap GenerateImage()
        {
            var result = new MyBitmap(Constants.BgWidth, Constants.BgHeight);
            var lines  = this.textBox.Lines.Where(l => !string.IsNullOrEmpty(l)).ToList();

            if (lines.Count != Constants.BgHeight / Constants.NesTileSize)
            {
                MessageBox.Show($"Invalid number of lines in the text box, should be {Constants.BgHeight / Constants.NesTileSize}");
                return(null);
            }

            var i = 0;

            foreach (var line in lines)
            {
                var split = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (split.Length != Constants.BgWidth / Constants.NesTileSize)
                {
                    MessageBox.Show($"Invalid number of ids in line {i}, should be {Constants.BgWidth / Constants.NesTileSize}");
                    return(null);
                }

                var ids = new List <int>();
                foreach (var s in split)
                {
                    int id;
                    if (!int.TryParse(s, out id))
                    {
                        MessageBox.Show($"Non-number in line {i}: {s}");
                        return(null);
                    }

                    ids.Add(id);
                }

                for (var j = 0; j < ids.Count; j++)
                {
                    var id   = ids[j];
                    var tile = this.tiles[id];
                    var x    = j * Constants.NesTileSize;
                    var y    = i * Constants.NesTileSize;
                    result.DrawImage(tile, x, y);
                }

                i++;
            }

            return(result);
        }
Exemple #4
0
        private MyBitmap CreateSingleBitmap(IEnumerable <MyBitmap> bitmaps)
        {
            var positions    = Packer.Pack(bitmaps.Select(b => b.Size), Constants.PickerWidth);
            var bitmapsCopy  = bitmaps.ToList();
            var backColor    = MyBitmap.NesGreyscale[0];
            var resultBitmap = new MyBitmap(1, 1, backColor);

            foreach (var tuple in positions)
            {
                var position = tuple.Item1;
                var size     = tuple.Item2;

                var bitmap = bitmapsCopy.First(b => b.Size == size);
                bitmapsCopy.Remove(bitmap);

                resultBitmap.DrawImage(bitmap, position.X, position.Y, true, backColor);
            }

            return(resultBitmap);
        }
Exemple #5
0
        private void LoadButtonClick(object sender, System.EventArgs e)
        {
            this.story = Story.Read(this.storyTextBox.Text);
            this.stringsConfig = StringsConfig.Read(this.stringsTextBox.Text);
            var tiles = new List<MyBitmap>();
            TitleDialog.ProcessFont(this.fontTextBox.Text, tiles);

            var strings = new List<StringToRedner>();

            foreach (var strData in this.story.Strings)
            {
                if (strData.X < 1 || strData.Y < 1)
                {
                    throw new System.Exception("Invalid string position");
                }

                var str = this.stringsConfig.Strings.First(s => s.Id == strData.StringId).Value;
                if (str.Length > 30)
                {
                    throw new System.Exception("Invalid string length");
                }

                strings.Add(new StringToRedner(strData.X, strData.Y, str.ToLower()));
            }

            strings.Add(new StringToRedner(PressStartX, PressStartY, PressStart));

            var bmp = new MyBitmap(512, 448, System.Drawing.Color.Black); // 448 means NTSC
            foreach (var str in strings)
            {
                var x = str.X;
                foreach (var chr in str.Str.ToCharArray())
                {
                    var tile = tiles[TitleDialog.Chars.IndexOf(chr)].Scale(BitmapZoom);
                    bmp.DrawImage(tile, x * Constants.SpriteWidth * BitmapZoom, (str.Y - 1) * Constants.SpriteHeight * BitmapZoom); // - 1 because of NTSC
                    x++;
                }
            }

            this.pictureBox.Image = bmp.ToBitmap();
        }
Exemple #6
0
        /// <summary>
        /// Special method for rendering the explosion.
        /// </summary>
        public Bitmap GetExplosionBitmap(
            Color backColor,
            bool applyPalettes,
            int zoom)
        {
            // Get flags for the request.
            var flags = GetFlags(applyPalettes, false, false, false);

            // Checked if a cached bitmap is available, return it if it is.
            var dictionary = this.cachedBitmaps[zoom - 1];

            if (dictionary.ContainsKey(flags))
            {
                return(dictionary[flags]);
            }

            // Create bitmap.
            var width  = Constants.ExplosionWidth;
            var height = Constants.ExplosionHeight;
            var image  = new MyBitmap(width, height, backColor);

            // Draw each sprite.
            foreach (var sprite in this.Sprites)
            {
                // Get the correct sprite image.
                var spriteImage = sprite.GetSprite(applyPalettes, sprite.VFlip, sprite.HFlip);

                // Draw the image.
                image.DrawImage(spriteImage, sprite.X, sprite.Y);
            }

            // Scale image.
            var result = image.Scale(zoom).ToBitmap();

            // Save result for later and return.
            dictionary.Add(flags, result);
            return(result);
        }
Exemple #7
0
        private void LoadButtonClick(object sender, EventArgs e)
        {
            var fileName = this.inputTextBox.Text;

            if (!File.Exists(fileName))
            {
                MessageBox.Show("File doesn't exit");
            }

            this.bitmap = MyBitmap.FromFile(fileName);

            if (this.bitmap.Width != Constants.BgWidth || this.bitmap.Height != Constants.BgHeight)
            {
                MessageBox.Show($"Incorrect size, should be {Constants.BgWidth}x{Constants.BgHeight}");
            }

            this.tiles     = new List <MyBitmap>();
            this.positions = new List <Point>();
            var indices = new int[32, 24];

            for (var y = 0; y < this.bitmap.Height / Constants.NesTileSize; y++)
            {
                for (var x = 0; x < this.bitmap.Width / Constants.NesTileSize; x++)
                {
                    var smallImage = bitmap.GetPart(x * Constants.NesTileSize, y * Constants.NesTileSize, Constants.NesTileSize, Constants.NesTileSize);
                    if (this.tiles.Any(v => v.Equals(smallImage)))
                    {
                        indices[x, y] = this.tiles.IndexOf(smallImage);
                    }
                    else
                    {
                        this.tiles.Add(smallImage);
                        this.positions.Add(new Point(x * Constants.NesTileSize, y * Constants.NesTileSize));
                        indices[x, y] = this.tiles.Count - 1;
                    }
                }
            }

            const int entryWidth        = 65;
            const int horizontalSpacing = 8;
            const int entriesInRow      = 7;
            const int leftPadding       = 12;
            const int imageWidth        = entryWidth + (entryWidth + horizontalSpacing) * (entriesInRow - 1) + leftPadding;
            const int entryHeight       = 33;
            const int verticalSpacing   = 2;
            const int topPadding        = 12;
            var       rowCount          = (this.tiles.Count + entriesInRow - 1) / entriesInRow;
            var       imageHeight       = rowCount * entryHeight + (rowCount - 1) * verticalSpacing + topPadding;

            this.smallImagesBitmap = new MyBitmap(imageWidth, imageHeight);

            var font = new Font("Calibri", 8);

            for (var i = 0; i < this.tiles.Count; i++)
            {
                var x        = (i % entriesInRow) * (entryWidth + horizontalSpacing) + leftPadding;
                var y        = (i / entriesInRow) * (entryHeight + verticalSpacing) + topPadding;
                var tile     = this.tiles[i].Scale(2);
                var subImage = new MyBitmap(entryWidth, entryHeight);
                subImage.DrawImage(tile, (entryWidth - tile.Width) / 2, 0);

                var tempBitmap = subImage.ToBitmap();
                using (var g = Graphics.FromImage(tempBitmap))
                {
                    g.DrawString(string.Format("{0:D3}: {1:D3}/{2:D3}", i, this.positions[i].X, this.positions[i].Y), font, Brushes.Black, 0, 18);
                }

                this.smallImagesBitmap.DrawImage(MyBitmap.FromBitmap(tempBitmap), x, y);
            }

            this.smallImagesPanel.BackgroundImage = this.smallImagesBitmap.ToBitmap();

            var str = string.Empty;

            for (var y = 0; y < this.bitmap.Height / Constants.NesTileSize; y++)
            {
                for (var x = 0; x < this.bitmap.Width / Constants.NesTileSize; x++)
                {
                    str += indices[x, y].ToString("D3") + " ";
                }

                str += Environment.NewLine;
            }

            this.textBox.Text = str;
            this.UpdateImage();
        }
Exemple #8
0
        /// <summary>
        /// Method for rendering a grid bitmap.
        /// </summary>
        public Bitmap GetGridBitmap(
            Color backColor,
            bool applyPalettes,
            bool showBoxes,
            bool vFlip,
            bool hFlip,
            int zoom,
            Offsets offsets,
            bool transparent   = false,
            bool transparentBg = false)
        {
            // Get flags for the request.
            var flags = GetFlags(applyPalettes, showBoxes, vFlip, hFlip, transparent, transparentBg);

            // Checked if a cached bitmap is available, return it if it is.
            var dictionary = this.cachedBitmaps[zoom - 1];

            if (dictionary.ContainsKey(flags))
            {
                return(dictionary[flags]);
            }

            // Create bitmap.
            var width  = this.Width * Constants.SpriteWidth;
            var height = this.Height * Constants.SpriteHeight;
            var image  = new MyBitmap(width, height, backColor);

            // Figure out flip.
            var isFlip = (hFlip || vFlip);

            // Draw each sprite.
            for (var spriteX = 0; spriteX < this.Width; spriteX++)
            {
                for (var spriteY = 0; spriteY < this.Height; spriteY++)
                {
                    // Sprites are aligned like:
                    //   1 2 3
                    //   4 5 6
                    var spriteId = spriteX + (spriteY * this.Width);
                    var sprite   = this.Sprites[spriteId];

                    // Figure out flips.
                    var shouldBeVFlip = sprite.VFlip ^ vFlip;
                    var shouldBeHFlip = sprite.HFlip ^ hFlip;

                    // Get the correct sprite image.
                    var spriteImage = sprite.GetSprite(applyPalettes, shouldBeVFlip, shouldBeHFlip, backColor);

                    // Calculate sprite's position.
                    var x = spriteX * Constants.SpriteWidth;
                    var y = spriteY * Constants.SpriteHeight;

                    if (vFlip)
                    {
                        y = height - y - Constants.SpriteHeight;
                    }

                    if (hFlip)
                    {
                        x = width - x - Constants.SpriteWidth;
                    }

                    // Draw the image.
                    image.DrawImage(spriteImage, x, y);
                }
            }

            if (showBoxes && offsets.XOff != 255)
            {
                image.DrawRectangle(MyBitmap.ThreatBoxColor, offsets.XOff, offsets.YOff, offsets.XOff + offsets.Width, offsets.YOff + offsets.Height);
            }

            // Scale image.
            var result = image.Scale(zoom).ToBitmap(transparent ? Constants.TransparentAlpha : 255, transparentBg ?  backColor : (Color?)null);

            // Save result for later and return.
            dictionary.Add(flags, result);
            return(result);
        }
Exemple #9
0
        /// <summary>
        /// Special method for rendering the player.
        /// </summary>
        public Bitmap GetPlayerBitmap(
            SpriteConfig config,
            Color backColor,
            bool applyPalettes,
            bool showBoxes,
            bool hFlip,
            int zoom,
            bool transparentBg = false)
        {
            // Get flags for the request.
            var flags = GetFlags(applyPalettes, showBoxes, false, hFlip, false, transparentBg);

            // Checked if a cached bitmap is available, return it if it is.
            var dictionary = this.cachedBitmaps[zoom - 1];

            if (dictionary.ContainsKey(flags))
            {
                return(dictionary[flags]);
            }

            // Assume game position equals the offsets.
            var gameX = Constants.PlayerXOffset;
            var gameY = Constants.PlayerYOffset;

            // Calculate image size. Get a max of all frames.
            var maxX   = config.Frames.Max(f => f.Sprites.Max(s => gameX + Player.GetXOffset(s, hFlip)));
            var maxY   = config.Frames.Max(f => f.Sprites.Max(s => gameY + Player.GetYOffset(s)));
            var width  = maxX + Constants.SpriteWidth;
            var height = maxY + Constants.SpriteHeight;
            var image  = new MyBitmap(width, height, backColor);

            // Draw each sprite.
            foreach (var sprite in this.Sprites)
            {
                // Get the correct sprite image.
                var spriteImage = sprite.GetSprite(applyPalettes, sprite.VFlip, sprite.HFlip ^ hFlip);

                // Draw the image.
                image.DrawImage(spriteImage, gameX + Player.GetXOffset(sprite, hFlip), gameY + Player.GetYOffset(sprite));
            }

            if (showBoxes)
            {
                // Platform box.
                var platformBoxX1 = gameX;
                var platformBoxY1 = gameY;
                var platformBoxX2 = platformBoxX1 + Constants.PlayerPlatformBoxWidth;
                var platformBoxY2 = platformBoxY1 + Constants.PlayerPlatformBoxHeight;
                image.DrawRectangle(MyBitmap.PlatformBoxColor, platformBoxX1, platformBoxY1, platformBoxX2, platformBoxY2);

                // Threat box.
                var threatBoxX1 = gameX + Constants.PlayerThreatBoxXOff;
                var threatBoxY1 = gameY + Constants.PlayerThreatBoxYOff;
                var threatBoxX2 = threatBoxX1 + Constants.PlayerThreatBoxWidth;
                var threatBoxY2 = threatBoxY1 + (this.Name == "Crouch" ? Constants.PlayerThreatBoxHeightCrouch : Constants.PlayerThreatBoxHeight);
                image.DrawRectangle(MyBitmap.ThreatBoxColor, threatBoxX1, threatBoxY1, threatBoxX2, threatBoxY2);

                // Gun point.
                var gunYOff = this.Name == "Crouch" ? Constants.PlayerGunYOffCrouch : Constants.PlayerGunYOff;
                var gunXOff = hFlip ? Constants.PlayerGunOXffL : Constants.PlayerGunOXffR;
                image.SetPixel(MyBitmap.GunColor, gameX + gunXOff, gameY + gunYOff);

                // Game position.
                image.SetPixel(MyBitmap.XYColor, gameX, gameY);
            }

            // Scale image.
            var result = image.Scale(zoom).ToBitmap(backgroundColor: transparentBg ? backColor : (Color?)null);

            // Save result for later and return.
            dictionary.Add(flags, result);
            return(result);
        }
Exemple #10
0
        private void GenerateChrImageAndSaveFiles(BackgroundConfig config, List <MyBitmap> sprites)
        {
            // Find the empty tile, move it to the end, update the config
            int emptyTileIndex = -1;

            for (var i = 0; i < sprites.Count; i++)
            {
                if (sprites[i].IsNesColor(0))
                {
                    emptyTileIndex = i;
                }
            }

            if (emptyTileIndex == -1)
            {
                throw new Exception("Empty tile not found for some reason");
            }

            // Move empty tile to the beginning.
            var emptyTile = sprites[emptyTileIndex];

            sprites.RemoveAt(emptyTileIndex);
            var newEmptyTileIndex = 0;

            sprites.Insert(0, emptyTile);

            // Update the config.
            foreach (var tile in config.Tiles)
            {
                var newSprites = new int[4];
                Array.Copy(tile.Sprites, newSprites, 4);
                for (var i = 0; i < 4; i++)
                {
                    if (newSprites[i] == emptyTileIndex)
                    {
                        newSprites[i] = newEmptyTileIndex;
                    }
                    else if (newSprites[i] < emptyTileIndex)
                    {
                        newSprites[i] = newSprites[i] + 1;
                    }
                }

                tile.Sprites = newSprites;
            }

            // Generate chr image
            var chrImage = new MyBitmap(Constants.SpriteWidth * Constants.ChrFileSpritesPerRow, Constants.SpriteHeight * Constants.ChrFileRows, Color.Black);
            {
                var x = 0;
                var y = 0;

                foreach (var sprite in sprites)
                {
                    chrImage.DrawImage(sprite, x, y);
                    x += 8;
                    if (x >= Constants.SpriteWidth * Constants.ChrFileSpritesPerRow)
                    {
                        x  = 0;
                        y += 8;
                    }
                }
            }

            // Generate actual chr file
            // CHR format:
            //  each sprite is 16 bytes:
            //  first 8 bytes are low bits per sprite row
            //  second 8 bytes are high bits per sprite row
            var bytes = new List <byte>();

            foreach (var sprite in sprites)
            {
                var lowBits  = new List <byte>();
                var highBits = new List <byte>();

                for (var y = 0; y < Constants.SpriteHeight; y++)
                {
                    byte lowBit  = 0;
                    byte highBit = 0;

                    for (var x = 0; x < Constants.SpriteWidth; x++)
                    {
                        lowBit  = (byte)(lowBit << 1);
                        highBit = (byte)(highBit << 1);

                        var pixel = sprite.GetNesPixel(x, y);

                        if (pixel == 1 || pixel == 3)
                        {
                            // low bit set
                            lowBit |= 1;
                        }

                        if (pixel == 2 || pixel == 3)
                        {
                            // high bit set
                            highBit |= 1;
                        }
                    }

                    lowBits.Add(lowBit);
                    highBits.Add(highBit);
                }

                bytes.AddRange(lowBits);
                bytes.AddRange(highBits);
            }

            while (bytes.Count < 4096)
            {
                bytes.Add(0);
            }

            // Save everything
            chrImage.ToBitmap().Save(outputImageTextBox.Text);

            config.Write(outputSpecTextBox.Text);

            if (File.Exists(outputChrTextBox.Text))
            {
                File.Delete(outputChrTextBox.Text);
            }

            File.WriteAllBytes(outputChrTextBox.Text, bytes.ToArray());
        }