// Get attack animation frames public static List <Bitmap> UnitAttack(CombatEventArgs e) { var animationFrames = new List <Bitmap>(); var map = e.Defender.Location.Map; // Which squares are to be drawn var coordsOffsetsToBeDrawn = new List <int[]> { new[] { -2, -4 }, new[] { 0, -4 }, new[] { 2, -4 }, new[] { -3, -3 }, new[] { -1, -3 }, new[] { 1, -3 }, new[] { 3, -3 }, new[] { -2, -2 }, new[] { 0, -2 }, new[] { 2, -2 }, new[] { -3, -1 }, new[] { -1, -1 }, new[] { 1, -1 }, new[] { 3, -1 }, new[] { -2, 0 }, new[] { 0, 0 }, new[] { 2, 0 }, new[] { -3, 1 }, new[] { -1, 1 }, new[] { 1, 1 }, new[] { 3, 1 }, new[] { -2, 2 }, new[] { 0, 2 }, new[] { 2, 2 }, new[] { -3, 3 }, new[] { -1, 3 }, new[] { 1, 3 }, new[] { 3, 3 }, new[] { -2, 4 }, new[] { 0, 4 }, new[] { 2, 4 } }; var defenderX = e.Defender.Location.X; var defenderY = e.Defender.Location.Y; var attackerX = e.Attacker.Location.X; var attackerY = e.Attacker.Location.Y; // First draw main bitmap with everything except the moving unit int[] coordsOffsetsPx; var mainBitmap = new Bitmap(6 * map.Xpx, 7 * map.Ypx, PixelFormat.Format32bppRgba); using (var g = new Graphics(mainBitmap)) { g.FillRectangle(Brushes.Black, new Rectangle(0, 0, 6 * map.Xpx, 7 * map.Ypx)); // Fill bitmap with black (necessary for correct drawing if image is on upper map edge) foreach (int[] coordsOffsets in coordsOffsetsToBeDrawn) { // Change coords of central offset int x = attackerX + coordsOffsets[0]; int y = attackerY + coordsOffsets[1]; coordsOffsetsPx = new[] { (coordsOffsets[0] + 2) * map.Xpx, (coordsOffsets[1] + 3) * map.Ypx }; if (x < 0 || y < 0 || x >= map.XDimMax || y >= map.YDim) { continue; // Make sure you're not drawing tiles outside map bounds } // Tiles var tile = map.TileC2(x, y); int civId = map.WhichCivsMapShown; if (map.MapRevealed || tile.Visibility[civId]) { Draw.Tile(g, x, y, map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1])); // Implement dithering in all 4 directions if necessary if (!map.MapRevealed) { for (int tileX = 0; tileX < 2; tileX++) { for (int tileY = 0; tileY < 2; tileY++) { int[] offset = { -1, 1 }; var xNew = x + offset[tileX]; var yNew = y + offset[tileY]; if (xNew >= 0 && xNew < map.XDimMax && yNew >= 0 && yNew < map.YDim) // Don't observe outside map limits { if (!map.IsTileVisibleC2(xNew, yNew, civId)) // Surrounding tile is not visible -> dither { Draw.Dither(g, tileX, tileY, map.Zoom, new Point(coordsOffsetsPx[0] + map.Xpx * tileX, coordsOffsetsPx[1] + map.Ypx * tileY)); } } } } } } // Units // If tile is with attacking & defending unit, draw these two first // TODO: this won't draw correctly if unit is in city if (x == attackerX && y == attackerY) { Draw.Unit(g, e.Attacker, e.Attacker.IsInStack, map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1] - map.Ypx)); } else if (x == defenderX && y == defenderY) { Draw.Unit(g, e.Defender, e.Defender.IsInStack, map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1] - map.Ypx)); } else if (tile.CityHere == null && tile.UnitsHere.Count > 0) // Other units { var unit = tile.GetTopUnit(); Draw.Unit(g, unit, unit.IsInStack, map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1] - map.Ypx)); } // Cities if (tile.CityHere != null) { Draw.City(g, tile.CityHere, true, map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1] - map.Ypx)); } } // City names // Add additional coords for drawing city names coordsOffsetsToBeDrawn.Add(new[] { -3, -5 }); coordsOffsetsToBeDrawn.Add(new[] { -1, -5 }); coordsOffsetsToBeDrawn.Add(new[] { 1, -5 }); coordsOffsetsToBeDrawn.Add(new[] { 3, -5 }); coordsOffsetsToBeDrawn.Add(new[] { -4, -2 }); coordsOffsetsToBeDrawn.Add(new[] { 4, -2 }); coordsOffsetsToBeDrawn.Add(new[] { -4, 0 }); coordsOffsetsToBeDrawn.Add(new[] { 4, 0 }); coordsOffsetsToBeDrawn.Add(new[] { -4, 2 }); coordsOffsetsToBeDrawn.Add(new[] { 4, 2 }); foreach (int[] coordsOffsets in coordsOffsetsToBeDrawn) { // Change coords of central offset int x = attackerX + coordsOffsets[0]; int y = attackerY + coordsOffsets[1]; if (x < 0 || y < 0 || x >= map.XDimMax || y >= map.YDim) { continue; // Make sure you're not drawing tiles outside map bounds } var tile = map.TileC2(x, y); if (tile.CityHere != null) { Draw.CityName(g, tile.CityHere, map.Zoom, new[] { coordsOffsets[0] + 2, coordsOffsets[1] + 3 }); } } } // Now draw the battle animation on top of attacking & defending unit // Number of battle rounds / 5 determines number of explosions (must be at least one). Each explosion has 8 frames. Point point; for (int explosion = 0; explosion < e.CombatRoundsAttackerWins.Count / 5; explosion++) { for (int frame = 0; frame < 8; frame++) { // Make a clone of the main bitmap in order to draw frames with unit on it var bitmapWithExplosions = new Bitmap(mainBitmap); using (var g = new Graphics(bitmapWithExplosions)) { // Draw changing HP of both units foreach (var coordsOffsets in coordsOffsetsToBeDrawn) { var x = attackerX + coordsOffsets[0]; var y = attackerY + coordsOffsets[1]; if (x == attackerX && y == attackerY) { Draw.UnitShield(g, e.Attacker.Type, e.Attacker.Owner.Id, e.Attacker.Order, e.Attacker.IsInStack, e.Attacker.Hitpoints[explosion * 5], e.Attacker.HitpointsBase, map.Zoom, new Point(2 * map.Xpx, 2 * map.Ypx)); Draw.UnitSprite(g, e.Attacker.Type, false, false, map.Zoom, new Point(2 * map.Xpx, 2 * map.Ypx)); } else if (x == defenderX && y == defenderY) { Draw.UnitShield(g, e.Defender.Type, e.Defender.Owner.Id, e.Defender.Order, e.Defender.IsInStack, e.Defender.Hitpoints[explosion * 5], e.Defender.HitpointsBase, map.Zoom, new Point((2 + coordsOffsets[0]) * map.Xpx, (2 + coordsOffsets[1]) * map.Ypx)); Draw.UnitSprite(g, e.Defender.Type, e.Defender.Order == OrderType.Sleep, e.Defender.Order == OrderType.Fortified, map.Zoom, new Point((2 + coordsOffsets[0]) * map.Xpx, (2 + coordsOffsets[1]) * map.Ypx)); } } // Draw explosion on defender point = e.CombatRoundsAttackerWins[explosion] ? new Point((int)(map.Xpx * (2.5 + defenderX - attackerX)), map.Ypx * (3 + (defenderY - attackerY))) : new Point((int)(map.Xpx * 2.5), map.Ypx * 3); Draw.BattleAnim(g, frame, map.Zoom, point); } animationFrames.Add(bitmapWithExplosions); } } return(animationFrames); }
private void Surface_Paint(object sender, PaintEventArgs e) { e.Graphics.AntiAlias = false; // Inner wallpaper e.Graphics.DrawImage(Images.ExtractBitmap(DLLs.Tiles, "cityStatusWallpaper").CropImage(new Rectangle(0, 0, 600, 400)), new Rectangle(11, 11, 600, 400)); // Text var font1 = new Font("Times New Roman", 14); Draw.Text(e.Graphics, "CITY STATUS", font1, Color.FromArgb(223, 223, 223), new Point(300, 24), true, true, Color.FromArgb(67, 67, 67), 2, 1); Draw.Text(e.Graphics, $"Holy Empire of the {Game.GetActiveCiv.Adjective}", font1, Color.FromArgb(223, 223, 223), new Point(300, 45), true, true, Color.FromArgb(67, 67, 67), 2, 1); Draw.Text(e.Graphics, $"{Game.GetActiveCiv.LeaderTitle} {Game.GetActiveCiv.LeaderName}: {Game.GetGameYearString}", font1, Color.FromArgb(223, 223, 223), new Point(300, 66), true, true, Color.FromArgb(67, 67, 67), 2, 1); // Cities var drawnCities = Game.GetActiveCiv.Cities.Skip(barVal0).Take(12).ToList(); for (int i = 0; i < drawnCities.Count; i++) { var city = drawnCities[i]; var font = new Font("Times New Roman", 11, FontStyle.Bold); // City image Draw.City(e.Graphics, city, true, 0, new Point(13 + 64 * ((barVal0 + i + 1) % 2), 78 + 24 * i)); // City name Draw.Text(e.Graphics, city.Name, font, Color.FromArgb(223, 223, 223), new Point(149, 87 + 24 * i), false, false, Color.FromArgb(67, 67, 67), 1, 1); // Food var offsetX = 254; var foodProd = new FormattedText() { Font = font, Text = city.FoodProduction.ToString(), ForegroundBrush = new SolidBrush(Color.FromArgb(223, 223, 223)) }; var foodProdShadow = new FormattedText() { Font = font, Text = city.FoodProduction.ToString(), ForegroundBrush = new SolidBrush(Color.FromArgb(67, 67, 67)) }; e.Graphics.DrawText(foodProdShadow, new Point(offsetX + 1, 87 + 24 * i + 1)); e.Graphics.DrawText(foodProd, new Point(offsetX, 87 + 24 * i)); offsetX += (int)foodProd.Measure().Width + 1; e.Graphics.DrawImage(CityImages.FoodBig, new Point(offsetX + +1, 87 + 24 * i)); // Production var prod = new FormattedText() { Font = font, Text = city.TotalProduction.ToString(), ForegroundBrush = new SolidBrush(Color.FromArgb(223, 223, 223)) }; var prodShadow = new FormattedText() { Font = font, Text = city.TotalProduction.ToString(), ForegroundBrush = new SolidBrush(Color.FromArgb(67, 67, 67)) }; offsetX += 16; e.Graphics.DrawText(prodShadow, new Point(offsetX + 1, 87 + 24 * i + 1)); e.Graphics.DrawText(prod, new Point(offsetX, 87 + 24 * i)); offsetX += (int)prod.Measure().Width + 1; e.Graphics.DrawImage(CityImages.SupportBig, new Point(offsetX, 87 + 24 * i)); // Trade var trade = new FormattedText() { Font = font, Text = city.Trade.ToString(), ForegroundBrush = new SolidBrush(Color.FromArgb(223, 223, 223)) }; var tradeShadow = new FormattedText() { Font = font, Text = city.Trade.ToString(), ForegroundBrush = new SolidBrush(Color.FromArgb(67, 67, 67)) }; offsetX += 16; e.Graphics.DrawText(tradeShadow, new Point(offsetX + 1, 87 + 24 * i + 1)); e.Graphics.DrawText(trade, new Point(offsetX, 87 + 24 * i)); offsetX += (int)trade.Measure().Width + 1; e.Graphics.DrawImage(CityImages.TradeBig, new Point(offsetX, 87 + 24 * i)); // Item in production var item = drawnCities[i].ItemInProduction; var itemText = new FormattedText() { Font = font, Text = item.GetDescription(), ForegroundBrush = new SolidBrush(item.Type == ItemType.Unit ? Color.FromArgb(255, 223, 79) : Color.FromArgb(223, 223, 223)) }; var itemShadowText = new FormattedText() { Font = font, Text = item.GetDescription(), ForegroundBrush = new SolidBrush(item.Type == ItemType.Unit ? Colors.Black : Color.FromArgb(67, 67, 67)) }; offsetX = 374; e.Graphics.DrawText(itemShadowText, new Point(offsetX + 1, 87 + 24 * i + 1)); e.Graphics.DrawText(itemText, new Point(offsetX, 87 + 24 * i)); offsetX += (int)itemText.Measure().Width + 3; var progressText = "(" + city.ShieldsProgress.ToString() + "/" + (10 * item.Cost).ToString() + ")"; Draw.Text(e.Graphics, progressText, font, Color.FromArgb(191, 191, 191), new Point(offsetX, 87 + 24 * i), false, false, Color.FromArgb(67, 67, 67), 1, 1); } }
private void Surface_Paint(object sender, PaintEventArgs e) { e.Graphics.AntiAlias = false; // Inner wallpaper e.Graphics.DrawImage(Images.ExtractBitmap(DLLs.Tiles, "attitudeAdvWallpaper").CropImage(new Rectangle(0, 0, 600, 400)), new Rectangle(11, 11, 600, 400)); // Text var font1 = new Font("Times New Roman", 14); Draw.Text(e.Graphics, "ATTITUDE ADVISOR", font1, Color.FromArgb(223, 223, 223), new Point(300, 24), true, true, Color.FromArgb(67, 67, 67), 2, 1); Draw.Text(e.Graphics, $"Holy Empire of the {Game.GetActiveCiv.Adjective}", font1, Color.FromArgb(223, 223, 223), new Point(300, 45), true, true, Color.FromArgb(67, 67, 67), 2, 1); Draw.Text(e.Graphics, $"{Game.GetActiveCiv.LeaderTitle} {Game.GetActiveCiv.LeaderName}: {Game.GetGameYearString}", font1, Color.FromArgb(223, 223, 223), new Point(300, 66), true, true, Color.FromArgb(67, 67, 67), 2, 1); // Cities var drawnCities = Game.GetActiveCiv.Cities.Skip(barVal0).Take(9).ToList(); for (int i = 0; i < drawnCities.Count; i++) { var city = drawnCities[i]; var font = new Font("Times New Roman", 11, FontStyle.Bold); // City image Draw.City(e.Graphics, city, true, 0, new Point(13 + 64 * ((barVal0 + i + 1) % 2), 78 + 32 * i)); // City name Draw.Text(e.Graphics, city.Name, font, Color.FromArgb(223, 223, 223), new Point(149, 87 + 32 * i), false, false, Color.FromArgb(67, 67, 67), 1, 1); // People var spacing = city.Size switch { int n when(n <= 10) => 28, int n when(n == 11) => 27, int n when(n == 12) => 25, int n when(n == 13) => 23, int n when(n == 14) => 21, int n when(n == 15) => 19, int n when(n == 16) => 18, int n when(n == 17) => 17, int n when(n == 18 || n == 19) => 15, int n when(n == 20) => 14, int n when(n == 21 || n == 22) => 13, int n when(n == 23 || n == 24) => 12, int n when(n == 25 || n == 26) => 11, int n when(n == 27 || n == 28) => 10, int n when(n >= 29 && n <= 31) => 9, int n when(n >= 32 && n <= 35) => 8, int n when(n >= 36 && n <= 40) => 7, int n when(n >= 41 && n <= 47) => 6, int n when(n >= 48 && n <= 56) => 5, int n when(n >= 57 && n <= 70) => 4, int n when(n >= 71 && n <= 93) => 3, int n when(n >= 94) => 2, _ => 28, }; PeopleType[] peoples = city.People; var offsetX = 254; int drawIndex; for (int p = 0; p < city.Size; p++) { drawIndex = (int)peoples[p]; if (p % 2 == 1 && (drawIndex == 0 || drawIndex == 2 || drawIndex == 4 || drawIndex == 6)) { drawIndex++; // Change men/woman appearance } var plpPic = CityImages.PeopleLarge[drawIndex, (int)city.Owner.Epoch]; e.Graphics.DrawImage(plpPic, offsetX + 5 + p * spacing, 81 + 32 * i); } } }
// Get animation frames for moving unit public static List <Bitmap> UnitMoving(Unit activeUnit) { List <Bitmap> animationFrames = new List <Bitmap>(); var Map = activeUnit.CurrentLocation.Map; // Get coords of central tile & which squares are to be drawn int[] activeUnitPrevXY = activeUnit.PrevXY; List <int[]> coordsOffsetsToBeDrawn = new List <int[]> { new[] { -2, -4 }, new[] { 0, -4 }, new[] { 2, -4 }, new[] { -3, -3 }, new[] { -1, -3 }, new[] { 1, -3 }, new[] { 3, -3 }, new[] { -2, -2 }, new[] { 0, -2 }, new[] { 2, -2 }, new[] { -3, -1 }, new[] { -1, -1 }, new[] { 1, -1 }, new[] { 3, -1 }, new[] { -2, 0 }, new[] { 0, 0 }, new[] { 2, 0 }, new[] { -3, 1 }, new[] { -1, 1 }, new[] { 1, 1 }, new[] { 3, 1 }, new[] { -2, 2 }, new[] { 0, 2 }, new[] { 2, 2 }, new[] { -3, 3 }, new[] { -1, 3 }, new[] { 1, 3 }, new[] { 3, 3 }, new[] { -2, 4 }, new[] { 0, 4 }, new[] { 2, 4 } }; // First draw main bitmap with everything except the moving unit int[] coordsOffsetsPx; var _mainBitmap = new Bitmap(6 * Map.Xpx, 7 * Map.Ypx, PixelFormat.Format32bppRgba); using (var g = new Graphics(_mainBitmap)) { g.FillRectangle(Brushes.Black, new Rectangle(0, 0, 6 * Map.Xpx, 7 * Map.Ypx)); // Fill bitmap with black (necessary for correct drawing if image is on upper map edge) foreach (int[] coordsOffsets in coordsOffsetsToBeDrawn) { // Change coords of central offset int x = activeUnitPrevXY[0] + coordsOffsets[0]; int y = activeUnitPrevXY[1] + coordsOffsets[1]; coordsOffsetsPx = new[] { (coordsOffsets[0] + 2) * Map.Xpx, (coordsOffsets[1] + 3) * Map.Ypx }; if (x < 0 || y < 0 || x >= Map.XDimMax || y >= Map.YDim) { continue; // Make sure you're not drawing tiles outside map bounds } // Tiles int civId = Map.WhichCivsMapShown; if (Map.IsTileVisibleC2(x, y, civId) || Map.MapRevealed) { Draw.Tile(g, x, y, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1])); // Implement dithering in all 4 directions if necessary if (!Map.MapRevealed) { for (int tileX = 0; tileX < 2; tileX++) { for (int tileY = 0; tileY < 2; tileY++) { int[] offset = { -1, 1 }; int xNew = x + offset[tileX]; int yNew = y + offset[tileY]; if (xNew >= 0 && xNew < Map.XDimMax && yNew >= 0 && yNew < Map.YDim) // Don't observe outside map limits { if (!Map.IsTileVisibleC2(xNew, yNew, civId)) // Surrounding tile is not visible -> dither { Draw.Dither(g, tileX, tileY, Map.Zoom, new Point(coordsOffsetsPx[0] + Map.Xpx * tileX, coordsOffsetsPx[1] + Map.Ypx * tileY)); } } } } } } // Units var tile = Map.TileC2(x, y); if (tile.CityHere == null) { // If unit is ship, remove units that are in it & remove active unit //var unitsHere = tile.UnitsHere.Where(u => u.InShip == null && u != activeUnit).ToList(); if (tile.UnitsHere.Count > 0 && tile.UnitsHere.Any(u => u != activeUnit)) { var unit = tile.GetTopUnit(u => u != activeUnit); Draw.Unit(g, unit, unit.IsInStack, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1] - Map.Ypx)); } } else { // Cities Draw.City(g, tile.CityHere, true, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1] - Map.Ypx)); } } // City names // Add additional coords for drawing city names coordsOffsetsToBeDrawn.Add(new[] { -3, -5 }); coordsOffsetsToBeDrawn.Add(new[] { -1, -5 }); coordsOffsetsToBeDrawn.Add(new[] { 1, -5 }); coordsOffsetsToBeDrawn.Add(new[] { 3, -5 }); coordsOffsetsToBeDrawn.Add(new[] { -4, -2 }); coordsOffsetsToBeDrawn.Add(new[] { 4, -2 }); coordsOffsetsToBeDrawn.Add(new[] { -4, 0 }); coordsOffsetsToBeDrawn.Add(new[] { 4, 0 }); coordsOffsetsToBeDrawn.Add(new[] { -4, 2 }); coordsOffsetsToBeDrawn.Add(new[] { 4, 2 }); foreach (int[] coordsOffsets in coordsOffsetsToBeDrawn) { // Change coords of central offset int x = activeUnitPrevXY[0] + coordsOffsets[0]; int y = activeUnitPrevXY[1] + coordsOffsets[1]; if (x < 0 || y < 0 || x >= Map.XDimMax || y >= Map.YDim) { continue; // Make sure you're not drawing tiles outside map bounds } var tile = Map.TileC2(x, y); if (tile.CityHere != null) { Draw.CityName(g, tile.CityHere, Map.Zoom, new[] { coordsOffsets[0] + 2, coordsOffsets[1] + 3 }); } } } // Now draw the moving unit on top of main bitmap int noFramesForOneMove = 8; for (int frame = 0; frame < noFramesForOneMove; frame++) { // Make a clone of the main bitmap in order to draw frames with unit on it var _bitmapWithMovingUnit = new Bitmap(_mainBitmap); using (var g = new Graphics(_bitmapWithMovingUnit)) { // Draw active unit on top of everything (except if it's city, then don't draw the unit in last frame) if (!(frame == noFramesForOneMove - 1 && activeUnit.CurrentLocation.CityHere != null)) { int[] unitDrawOffset = { activeUnit.X - activeUnit.PrevXY[0], activeUnit.Y - activeUnit.PrevXY[1] }; unitDrawOffset[0] *= Map.Xpx / noFramesForOneMove * (frame + 1); unitDrawOffset[1] *= Map.Ypx / noFramesForOneMove * (frame + 1); Draw.Unit(g, activeUnit, activeUnit.CarriedUnits.Count > 0, Map.Zoom, new Point(2 * Map.Xpx + unitDrawOffset[0], 2 * Map.Ypx + unitDrawOffset[1])); } } animationFrames.Add(_bitmapWithMovingUnit); } return(animationFrames); }
// Get animation frames for moving unit public static List <Bitmap> UnitMoving(IUnit activeUnit) { List <Bitmap> animationFrames = new List <Bitmap>(); // Get coords of central tile & which squares are to be drawn int[] activeUnitPrevXY = activeUnit.PrevXY; List <int[]> coordsOffsetsToBeDrawn = new List <int[]> { new int[] { -2, -4 }, new int[] { 0, -4 }, new int[] { 2, -4 }, new int[] { -3, -3 }, new int[] { -1, -3 }, new int[] { 1, -3 }, new int[] { 3, -3 }, new int[] { -2, -2 }, new int[] { 0, -2 }, new int[] { 2, -2 }, new int[] { -3, -1 }, new int[] { -1, -1 }, new int[] { 1, -1 }, new int[] { 3, -1 }, new int[] { -2, 0 }, new int[] { 0, 0 }, new int[] { 2, 0 }, new int[] { -3, 1 }, new int[] { -1, 1 }, new int[] { 1, 1 }, new int[] { 3, 1 }, new int[] { -2, 2 }, new int[] { 0, 2 }, new int[] { 2, 2 }, new int[] { -3, 3 }, new int[] { -1, 3 }, new int[] { 1, 3 }, new int[] { 3, 3 }, new int[] { -2, 4 }, new int[] { 0, 4 }, new int[] { 2, 4 } }; // First draw main bitmap with everything except the moving unit int[] coordsOffsetsPx; var _mainBitmap = new Bitmap(6 * Map.Xpx, 7 * Map.Ypx, PixelFormat.Format32bppRgba); using (var g = new Graphics(_mainBitmap)) { g.FillRectangle(Brushes.Black, new Rectangle(0, 0, 6 * Map.Xpx, 7 * Map.Ypx)); // Fill bitmap with black (necessary for correct drawing if image is on upper map edge) foreach (int[] coordsOffsets in coordsOffsetsToBeDrawn) { // Change coords of central offset int x = activeUnitPrevXY[0] + coordsOffsets[0]; int y = activeUnitPrevXY[1] + coordsOffsets[1]; coordsOffsetsPx = new int[] { (coordsOffsets[0] + 2) * Map.Xpx, (coordsOffsets[1] + 3) * Map.Ypx }; if (x < 0 || y < 0 || x >= 2 * Map.Xdim || y >= Map.Ydim) { continue; // Make sure you're not drawing tiles outside map bounds } // Tiles int civId = Map.WhichCivsMapShown; if (Map.IsTileVisibleC2(x, y, civId) || Map.MapRevealed) { Draw.Tile(g, x, y, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1])); // Implement dithering in all 4 directions if necessary if (!Map.MapRevealed) { for (int tileX = 0; tileX < 2; tileX++) { for (int tileY = 0; tileY < 2; tileY++) { int[] offset = new int[] { -1, 1 }; int xNew = x + offset[tileX]; int yNew = y + offset[tileY]; if (xNew >= 0 && xNew < 2 * Map.Xdim && yNew >= 0 && yNew < Map.Ydim) // Don't observe outside map limits { if (!Map.IsTileVisibleC2(xNew, yNew, civId)) // Surrounding tile is not visible -> dither { Draw.Dither(g, tileX, tileY, Map.Zoom, new Point(coordsOffsetsPx[0] + Map.Xpx * tileX, coordsOffsetsPx[1] + Map.Ypx * tileY)); } } } } } } // Units List <IUnit> unitsHere = Game.UnitsHere(x, y); // If active unit is in this list-- > remove it if (unitsHere.Contains(activeUnit)) { unitsHere.Remove(activeUnit); } if (unitsHere.Count > 0) { IUnit unit; // If this is not tile with active unit or viewing piece, draw last unit on stack if (!unitsHere.Contains(activeUnit)) { unit = unitsHere.Last(); if (!unit.IsInCity) { Draw.Unit(g, unit, unitsHere.Count > 1, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1] - Map.Ypx)); } } } // Cities City city = Game.CityHere(x, y); if (city != null) { Draw.City(g, city, true, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1] - Map.Ypx)); } } // City names // Add additional coords for drawing city names coordsOffsetsToBeDrawn.Add(new int[] { -3, -5 }); coordsOffsetsToBeDrawn.Add(new int[] { -1, -5 }); coordsOffsetsToBeDrawn.Add(new int[] { 1, -5 }); coordsOffsetsToBeDrawn.Add(new int[] { 3, -5 }); coordsOffsetsToBeDrawn.Add(new int[] { -4, -2 }); coordsOffsetsToBeDrawn.Add(new int[] { 4, -2 }); coordsOffsetsToBeDrawn.Add(new int[] { -4, 0 }); coordsOffsetsToBeDrawn.Add(new int[] { 4, 0 }); coordsOffsetsToBeDrawn.Add(new int[] { -4, 2 }); coordsOffsetsToBeDrawn.Add(new int[] { 4, 2 }); foreach (int[] coordsOffsets in coordsOffsetsToBeDrawn) { // Change coords of central offset int x = activeUnitPrevXY[0] + coordsOffsets[0]; int y = activeUnitPrevXY[1] + coordsOffsets[1]; if (x < 0 || y < 0 || x >= 2 * Map.Xdim || y >= Map.Ydim) { continue; // Make sure you're not drawing tiles outside map bounds } City city = Game.CityHere(x, y); if (city != null) { Draw.CityName(g, city, Map.Zoom, new int[] { coordsOffsets[0] + 2, coordsOffsets[1] + 3 }); } } } // Now draw the moving unit on top of main bitmap int noFramesForOneMove = 8; for (int frame = 0; frame < noFramesForOneMove; frame++) { // Make a clone of the main bitmap in order to draw frames with unit on it var _bitmapWithMovingUnit = new Bitmap(_mainBitmap); using (var g = new Graphics(_bitmapWithMovingUnit)) { // Draw active unit on top of everything //int[] activeUnitDrawOffset = new int[] { 0, 0 }; //switch (Game.ActiveUnit.PrevXY) //{ // case 0: activeUnitDrawOffset = new int[] { 1, -1 }; break; // case 1: activeUnitDrawOffset = new int[] { 2, 0 }; break; // case 2: activeUnitDrawOffset = new int[] { 1, 1 }; break; // case 3: activeUnitDrawOffset = new int[] { 0, 2 }; break; // case 4: activeUnitDrawOffset = new int[] { -1, 1 }; break; // case 5: activeUnitDrawOffset = new int[] { -2, 0 }; break; // case 6: activeUnitDrawOffset = new int[] { -1, -1 }; break; // case 7: activeUnitDrawOffset = new int[] { 0, -2 }; break; //} int[] unitDrawOffset = new int[] { activeUnit.X - activeUnit.PrevXY[0], activeUnit.Y - activeUnit.PrevXY[1] }; unitDrawOffset[0] *= Map.Xpx / noFramesForOneMove * (frame + 1); unitDrawOffset[1] *= Map.Ypx / noFramesForOneMove * (frame + 1); Draw.Unit(g, activeUnit, false, Map.Zoom, new Point(2 * Map.Xpx + unitDrawOffset[0], 2 * Map.Ypx + unitDrawOffset[1])); } animationFrames.Add(_bitmapWithMovingUnit); } return(animationFrames); }
// Get animation frames for waiting unit/view piece public static List <Bitmap> Waiting(int[] activeXY) { var animationFrames = new List <Bitmap>(); // Get coords of central tile & which squares are to be drawn var coordsOffsetsToBeDrawn = new List <int[]> { new int[] { 0, -2 }, new int[] { -1, -1 }, new int[] { 1, -1 }, new int[] { 0, 0 }, new int[] { -1, 1 }, new int[] { 1, 1 }, new int[] { 0, 2 } }; // Get 2 frames (one with and other without the active unit/moving piece) int[] coordsOffsetsPx; int x, y; for (int frame = 0; frame < 2; frame++) { var _bitmap = new Bitmap(2 * Map.Xpx, 3 * Map.Ypx, PixelFormat.Format32bppRgba); using (var g = new Graphics(_bitmap)) { // Fill bitmap with black (necessary for correct drawing if image is on upper map edge) g.FillRectangle(Brushes.Black, new Rectangle(0, 0, 2 * Map.Xpx, 3 * Map.Ypx)); foreach (int[] coordsOffsets in coordsOffsetsToBeDrawn) { // Change coords of central offset x = activeXY[0] + coordsOffsets[0]; y = activeXY[1] + coordsOffsets[1]; coordsOffsetsPx = new int[] { coordsOffsets[0] * Map.Xpx, coordsOffsets[1] * Map.Ypx }; if (x < 0 || y < 0 || x >= 2 * Map.Xdim || y >= Map.Ydim) { continue; // Make sure you're not drawing tiles outside map bounds } // Tiles Draw.Tile(g, x, y, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1] + Map.Ypx)); // Units List <IUnit> unitsHere = Game.UnitsHere(x, y); if (unitsHere.Count > 0 && Game.CityHere(x, y) == null) { IUnit unit; // If this is not tile with active unit or viewing piece, draw last unit on stack if (!(x == activeXY[0] && y == activeXY[1]) || Map.ViewPieceMode) { unit = unitsHere.Last(); Draw.Unit(g, unit, unit.IsInStack, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1])); } } // City City city = Game.CityHere(x, y); if (city != null) { Draw.City(g, city, true, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1])); } // Draw active unit if it's not moving if (unitsHere.Count > 0 && x == activeXY[0] && y == activeXY[1] && !Map.ViewPieceMode) { // Draw unit only for 1st frame if (frame == 0) { Draw.Unit(g, Game.GetActiveUnit, Game.GetActiveUnit.IsInStack, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1])); } } } // Gridlines if (Game.Options.Grid) { foreach (int[] coordsOffsets in coordsOffsetsToBeDrawn) { coordsOffsetsPx = new int[] { coordsOffsets[0] * Map.Xpx, coordsOffsets[1] * Map.Ypx + Map.Ypx }; Draw.Grid(g, Map.Zoom, new Point(coordsOffsetsPx[0], coordsOffsetsPx[1])); } } // City names coordsOffsetsToBeDrawn.Add(new int[] { -2, -2 }); coordsOffsetsToBeDrawn.Add(new int[] { 2, -2 }); coordsOffsetsToBeDrawn.Add(new int[] { -1, -3 }); coordsOffsetsToBeDrawn.Add(new int[] { 1, -3 }); foreach (int[] coordsOffsets in coordsOffsetsToBeDrawn) { // Change coords of central offset x = activeXY[0] + coordsOffsets[0]; y = activeXY[1] + coordsOffsets[1]; if (x < 0 || y < 0 || x >= 2 * Map.Xdim || y >= Map.Ydim) { continue; // Make sure you're not drawing tiles outside map bounds } City city = Game.CityHere(x, y); if (city != null) { Draw.CityName(g, city, Map.Zoom, new int[] { coordsOffsets[0], coordsOffsets[1] + 1 }); } } // View piece (is drawn on top of everything) if (Map.ViewPieceMode) { if (frame == 1) { Draw.ViewPiece(g, Map.Zoom, new Point(0, Map.Ypx)); } } } animationFrames.Add(_bitmap); } return(animationFrames); }
/// <summary> /// Make a bitmap of a part of map. /// </summary> /// <param name="civ">Map view of a of tribe (tribe's id).</param> /// <param name="startX">Starting X-coord shown on map.</param> /// <param name="startY">Starting Y-coord shown on map.</param> /// <param name="width">Width of map shown.</param> /// <param name="height">Height of map shown.</param> /// <param name="flatEarth">Flat earth map?</param> /// <param name="mapRevealed">Is map revealed?</param> /// <param name="showActiveUnit"></param> /// <param name="highlightList"></param> /// <param name="pathDebug"></param> /// <returns></returns> public static Bitmap MapPart(int civ, int startX, int startY, int width, int height, bool flatEarth, bool mapRevealed, bool showActiveUnit, IList <Tile> highlightList, Dictionary <Tile, Route> pathDebug) { // Define a bitmap for drawing var mapPic = new Bitmap(Map.Xpx * (2 * width + 1), Map.Ypx * (height + 1), PixelFormat.Format32bppRgba); // Draw map var cityList = new List <City>(); // Make a list of cities on visible map + their locations so you can draw city names using var g = new Graphics(mapPic); var activeUnit = Game.ActiveUnit; // Draw for (int _row = -2; _row < height + 2; _row++) { for (int _col = -2; _col < width; _col++) { // Determine column index in civ2-style coords int col = 2 * _col + (_row % 2); int row = _row; // Don't draw beyond borders var xC2 = startX + col; var yC2 = startY + row; if (xC2 < 0 || yC2 < 0 || xC2 >= Map.XDimMax || yC2 >= Map.YDim) { continue; } var tile = Map.TileC2(xC2, yC2); // Draw only if the tile is visible for each civ if (!mapRevealed && !tile.Visibility[civ]) { continue; } // Tiles Draw.Tile(g, xC2, yC2, Map.Zoom, new Point(Map.Xpx * col, Map.Ypx * row)); // Implement dithering in all 4 directions where non-visible tiles are if (!mapRevealed) { int[] offset = new int[] { -1, 1 }; for (int tileX = 0; tileX < 2; tileX++) { for (int tileY = 0; tileY < 2; tileY++) { int colNew = xC2 + offset[tileX]; int rowNew = yC2 + offset[tileY]; if (colNew >= 0 && colNew < Map.XDimMax && rowNew >= 0 && rowNew < Map.YDim) // Don't observe outside map limits { if (!Map.IsTileVisibleC2(colNew, rowNew, civ)) // Surrounding tile is not visible -> dither { g.DrawImage(MapImages.Terrains[Map.MapIndex].DitherMask[tileX * 2 + tileY], Map.Xpx * (col + tileX), Map.Ypx * (row + tileY)); } } } } } // Units var unitsHere = tile.UnitsHere; if (unitsHere.Count > 0 && (showActiveUnit || unitsHere.All(u => u != activeUnit)) && Map.IsCurrentlyVisible(tile)) { Unit unit = unitsHere.Last(); if (unitsHere.Any(u => u.Domain == UnitGAS.Sea)) { unit = unitsHere.Last(u => u.Domain == UnitGAS.Sea); // Show naval unit } if (!unit.IsInCity) { Draw.Unit(g, unit, unitsHere.Count > 1, Map.Zoom, new Point(Map.Xpx * col, Map.Ypx * (row - 1))); } } // Cities var city = tile.CityHere; if (city != null) { Draw.City(g, city, true, Map.Zoom, new Point(Map.Xpx * col, Map.Ypx * (row - 1))); // Add city drawn on map & its position to list for drawing city names cityList.Add(city); } if (highlightList != null && highlightList.Contains(tile)) { Draw.ViewPiece(g, Map.Zoom, new Point(Map.Xpx * col, Map.Ypx * (row - 0))); } if (pathDebug != null && pathDebug.ContainsKey(tile)) { g.DrawText(new Font("Times New Roman", 10.ZoomScale(Map.Zoom), FontStyle.Bold), Colors.Black, new Point(Map.Xpx * col + Map.Xpx, Map.Ypx * row), $"{pathDebug[tile].Steps}:{pathDebug[tile].Cost}"); } } } // Grid if (Game.Options.Grid) { for (int _row = 0; _row < height; _row++) { for (int _col = 0; _col < width; _col++) { // Determine column index in civ2-style coords int col = 2 * _col + (_row % 2); int row = _row; // Draw only if the tile is visible for each civ (index=8...whole map visible) if ((civ < 8 && Map.IsTileVisibleC2(startX + col, startY + row, civ)) || civ == 8) { Draw.Grid(g, Map.Zoom, new Point(Map.Xpx * col, Map.Ypx * row)); //g.DrawImage(ModifyImage.Resize(Images.GridLines, zoom), 4 * (8 + zoom) * col, 2 * (8 + zoom) * row); } } } } // City name text is drawn last foreach (City city in cityList) { int[] destSq = new int[] { city.X - startX, city.Y - startY }; Draw.CityName(g, city, Map.Zoom, destSq); } return(mapPic); }
// civId // = 0...7 for 8 civs (including barbarians with civId=7) // = 8 for revealed map //public static Bitmap DrawMap(int civ, bool flatEarth) // Draw for normal zoom level //{ // // Define a bitmap for drawing // var mapPic = new Bitmap(32 * (2 * Map.Xdim + 1), 16 * (2 * Map.Ydim + 1)); // // Draw map // int zoom = 0; // Default zoom // using (Graphics g = Graphics.FromImage(mapPic)) // { // // Define starting and ending coords for drawing // int colStart, colEnd; // if (flatEarth) // { // colStart = 0; // colEnd = Map.Xdim; // } // else // Round world --> go few tiles beyond E and W borders in order to fill up blank space at map edge // { // colStart = -2; // colEnd = Map.Xdim + 2; // } // // Draw // for (int _row = 0; _row < Map.Ydim; _row++) // { // for (int _col = colStart; _col < colEnd; _col++) // { // // Determine column index in civ2-style coords // int col = 2 * _col + (_row % 2); // int row = _row; // // Draw only if the tile is visible for each civ (index=8...whole map visible) // if ((civ < 8 && Map.IsTileVisibleC2(col, row, civ)) || civ == 8) // { // // Tiles // g.DrawImage(Map.TileC2(col, row).Graphic, 32 * col, 16 * row); // // Implement dithering in all 4 directions where non-visible tiles are // if (civ != 8) // { // int[] offset = new int[] { -1, 1 }; // for (int tileX = 0; tileX < 2; tileX++) // { // for (int tileY = 0; tileY < 2; tileY++) // { // int colNew = col + offset[tileX]; // int rowNew = row + offset[tileY]; // if (colNew >= 0 && colNew < 2 * Map.Xdim && rowNew >= 0 && rowNew < Map.Ydim) // Don't observe outside map limits // { // if (!Map.IsTileVisibleC2(colNew, rowNew, civ)) // Surrounding tile is not visible -> dither // g.DrawImage(Images.DitherDots[tileX, tileY], 32 * (col + tileX), 16 * (row + tileY)); // } // } // } // } // // Units // List<IUnit> unitsHere = Game.GetUnits.Where(u => u.X == col && u.Y == row).ToList(); // if (unitsHere.Count > 0) // { // IUnit unit = unitsHere.Last(); // if (!unit.IsInCity) // { // Draw.Unit(g, unit, unitsHere.Count > 1, zoom, new Point(32 * col, 16 * row - 16)); // } // } // // Cities // City city = Game.GetCities.Find(c => c.X == col && c.Y == row); // if (city != null) // { // Draw.City(g, city, true, zoom, new Point(32 * col, 16 * row - 16)); // } // } // } // } // // City name text is drawn last // foreach (City city in Game.GetCities) // { // //int[] ColRow = Ext.Civ2xy(new int[] { city.X, city.Y }); // Real coords from civ2 coords // if ((civ < 8 && Map.IsTileVisibleC2(city.X, city.Y, civ)) || civ == 8) // { // //Bitmap cityNameBitmap = Draw.CityName(city, zoom); // //g.DrawImage(cityNameBitmap, 32 * city.X + 32 - (cityNameBitmap.Width / 2), 16 * city.Y + 3 * 8); // } // } // } // return mapPic; //} public static Bitmap MapPart(int civ, int startX, int startY, int width, int height, bool flatEarth, bool mapRevealed) { // Define a bitmap for drawing var mapPic = new Bitmap(Map.Xpx * (2 * width + 1), Map.Ypx * (height + 1), PixelFormat.Format32bppRgba); // Draw map var cityList = new List <City>(); // Make a list of cities on visible map + their locations so you can draw city names using (var g = new Graphics(mapPic)) { // Draw for (int _row = 0; _row < height; _row++) { for (int _col = 0; _col < width; _col++) { // Determine column index in civ2-style coords int col = 2 * _col + (_row % 2); int row = _row; // Draw only if the tile is visible for each civ if (Map.IsTileVisibleC2(startX + col, startY + row, civ) || mapRevealed) { // Tiles Draw.Tile(g, startX + col, startY + row, Map.Zoom, new Point(Map.Xpx * col, Map.Ypx * row)); // Implement dithering in all 4 directions where non-visible tiles are if (!mapRevealed) { int[] offset = new int[] { -1, 1 }; for (int tileX = 0; tileX < 2; tileX++) { for (int tileY = 0; tileY < 2; tileY++) { int colNew = startX + col + offset[tileX]; int rowNew = startY + row + offset[tileY]; if (colNew >= 0 && colNew < 2 * Map.Xdim && rowNew >= 0 && rowNew < Map.Ydim) // Don't observe outside map limits { if (!Map.IsTileVisibleC2(colNew, rowNew, civ)) // Surrounding tile is not visible -> dither { g.DrawImage(Images.DitherDots[tileX, tileY], Map.Xpx * (col + tileX), Map.Ypx * (row + tileY)); } } } } } // Units List <IUnit> unitsHere = Game.GetUnits.Where(u => u.X == startX + col && u.Y == startY + row).ToList(); if (unitsHere.Count > 0) { IUnit unit = unitsHere.Last(); //if (unitsHere.Contains(Game.GetActiveUnit) && Main.ViewPieceMode) //{ //} if (!unit.IsInCity) { Draw.Unit(g, unit, unitsHere.Count > 1, Map.Zoom, new Point(Map.Xpx * col, Map.Ypx * (row - 1))); } } // Cities City city = Game.GetCities.Find(c => c.X == startX + col && c.Y == startY + row); if (city != null) { Draw.City(g, city, true, Map.Zoom, new Point(Map.Xpx * col, Map.Ypx * (row - 1))); // Add city drawn on map & its position to list for drawing city names cityList.Add(city); } } } } // Grid if (Game.Options.Grid) { for (int _row = 0; _row < height; _row++) { for (int _col = 0; _col < width; _col++) { // Determine column index in civ2-style coords int col = 2 * _col + (_row % 2); int row = _row; // Draw only if the tile is visible for each civ (index=8...whole map visible) if ((civ < 8 && Map.IsTileVisibleC2(startX + col, startY + row, civ)) || civ == 8) { Draw.Grid(g, Map.Zoom, new Point(Map.Xpx * col, Map.Ypx * row)); //g.DrawImage(ModifyImage.Resize(Images.GridLines, zoom), 4 * (8 + zoom) * col, 2 * (8 + zoom) * row); } } } } // City name text is drawn last foreach (City city in cityList) { int[] destSq = new int[] { city.X - startX, city.Y - startY }; Draw.CityName(g, city, Map.Zoom, destSq); } } return(mapPic); }
// Draw resource map public static Bitmap CityResourcesMap(City city, int zoom) { var map = new Bitmap(4 * 8 * (8 + zoom), 4 * 4 * (8 + zoom), PixelFormat.Format32bppRgba); using (var g = new Graphics(map)) { // First draw squares around city int newX, newY; City cityHere; List <IUnit> unitsHere; for (int y_ = -3; y_ <= 3; y_++) { for (int x_ = -3; x_ <= 3; x_++) { if ((x_ == -1 && y_ == -3) || (x_ == 1 && y_ == -3) || (x_ == -2 && y_ == -2) || (x_ == 0 && y_ == -2) || (x_ == 2 && y_ == -2) || (x_ == -3 && y_ == -1) || (x_ == -1 && y_ == -1) || (x_ == 1 && y_ == -1) || (x_ == 3 && y_ == -1) || (x_ == -2 && y_ == 0) || (x_ == 0 && y_ == 0) || (x_ == 2 && y_ == 0) || (x_ == -3 && y_ == 1) || (x_ == -1 && y_ == 1) || (x_ == 1 && y_ == 1) || (x_ == 3 && y_ == 1) || (x_ == -2 && y_ == 2) || (x_ == 0 && y_ == 2) || (x_ == 2 && y_ == 2) || (x_ == -1 && y_ == 3) || (x_ == 1 && y_ == 3)) { newX = city.X + x_; newY = city.Y + y_; // First draw blank tiles using var blankPic = Images.Blank.Resize(zoom); g.DrawImage(blankPic, 4 * (8 + zoom) * (x_ + 3), 2 * (8 + zoom) * (y_ + 3)); // Then draw tiles if they are visible if (Map.IsTileVisibleC2(newX, newY, city.Owner.Id)) { using var mapPic = Images.MapTileGraphicC2(newX, newY).Resize(zoom); g.DrawImage(mapPic, 4 * (8 + zoom) * (x_ + 3), 2 * (8 + zoom) * (y_ + 3)); } // TODO: implement dithering on edges or depending on where invisible tiles are // Draw cities cityHere = Game.CityHere(newX, newY); if (cityHere != null) { Draw.City(g, cityHere, false, zoom, new Point(4 * (8 + zoom) * (x_ + 3), 2 * (8 + zoom) * (y_ + 3) - 2 * (8 + zoom))); } //g.DrawImage(cityHere.Graphic(false, zoom), 4 * (8 + zoom) * (x_ + 3), 2 * (8 + zoom) * (y_ + 3) - 2 * (8 + zoom)); // Draw units unitsHere = Game.UnitsHere(newX, newY).FindAll(unit => (unit.Owner != Game.GetActiveCiv) && (unit.Type != Civ2engine.Enums.UnitType.Settlers)); //if (unitsHere.Count > 0 && cityHere == null) // g.DrawImage(unitsHere.Last().Graphic(true, zoom), 4 * (8 + zoom) * (x_ + 3), 2 * (8 + zoom) * (y_ + 3) - 2 * (8 + zoom)); // TODO: make sure you're not drawing beyond map edges //if (newX >= 0 && newX < 2 * Data.MapXdim && newY >= 0 && newY < Data.MapYdim) image = TerrainBitmap((newX - (newY % 2)) / 2, newY); } } } // Then draw food/shield/trade icons around the city (21 squares around city) int[,] offsets = new int[21, 2] { { 0, 0 }, { -1, -3 }, { -3, -1 }, { -3, 1 }, { -1, 3 }, { 1, 3 }, { 3, 1 }, { 3, -1 }, { 1, -3 }, { -2, -2 }, { -2, 2 }, { 2, 2 }, { 2, -2 }, { 0, -2 }, { -1, -1 }, { -2, 0 }, { -1, 1 }, { 0, 2 }, { 1, 1 }, { 2, 0 }, { 1, -1 } }; // offset of squares from city (0,0) int[] cityFood = city.FoodDistribution; int[] cityShld = city.ShieldDistribution; int[] cityTrad = city.TradeDistribution; for (int i = 0; i < 21; i++) { if (city.DistributionWorkers[i]) { // First count all icons on this square to determine the spacing between icons (10 = no spacing, 15 = no spacing @ 50% scaled) int spacing; switch (cityFood[i] + cityShld[i] + cityTrad[i]) { case 1: case 2: spacing = 11; break; // normal=11, big = 17, 1 pixel gap case 3: spacing = 10; break; // normal=10, big = 15, no gap case 4: spacing = 7; break; // normal=7, big = 11 case 5: spacing = 5; break; // normal=5, big = 8 case 6: spacing = 4; break; // normal=4, big = 6 case 7: case 8: spacing = 3; break; // normal=3, big = 5 case 9: spacing = 2; break; // normal=2, big = 3 case 10: spacing = 1; break; // normal=1, big = 2 default: spacing = 1; break; // normal=1, big = 2 } // First draw food, then shields, then trade icons int x_offset = 4 * (8 + zoom) - ((cityFood[i] + cityShld[i] + cityTrad[i] - 1) * spacing + 15) / 2; int y_offset = 9; for (int j = 0; j < cityFood[i]; j++) { g.DrawImage(Images.CityFoodSmall, x_offset + (3 + offsets[i, 0]) * 4 * (8 + zoom) + j * spacing, y_offset + (3 + offsets[i, 1]) * 2 * (8 + zoom)); } for (int j = 0; j < cityShld[i]; j++) { g.DrawImage(Images.CitySupportSmall, x_offset + (3 + offsets[i, 0]) * 4 * (8 + zoom) + (cityFood[i] + j) * spacing, y_offset + (3 + offsets[i, 1]) * 2 * (8 + zoom)); } for (int j = 0; j < cityTrad[i]; j++) { g.DrawImage(Images.CityTradeSmall, x_offset + (3 + offsets[i, 0]) * 4 * (8 + zoom) + (cityFood[i] + cityShld[i] + j) * spacing, y_offset + (3 + offsets[i, 1]) * 2 * (8 + zoom)); } } } } return(map); }