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