// Draw icons in city resources (surplus < 0 is hunger) public static Bitmap CityResources(City city)//, int foodIcons, int surplusIcons, int tradeIcons, int corruptionIcons, int taxIcons, int luxIcons, int sciIcons, int supportIcons, int productionIcons) { int x_size = 226; int y_size = 151; var icons = new Bitmap(x_size, y_size); using (var g = Graphics.FromImage(icons)) { using var _font = new Font("Arial", 9, FontStyle.Bold); // FOOD // Text Draw.Text(g, $"Food: {city.Food}", _font, StringAlignment.Near, StringAlignment.Near, Color.FromArgb(87, 171, 39), new Point(0, 0), Color.Black, 1, 1); Draw.Text(g, $"Surplus: {city.SurplusHunger}", _font, StringAlignment.Far, StringAlignment.Near, Color.FromArgb(63, 139, 31), new Point(225, 0), Color.Black, 1, 1); // Number of food+surplus/hunger icons determines spacing between icons int spacing; switch (city.Food + Math.Abs(city.SurplusHunger)) { case int n when(n >= 1 && n <= 15): spacing = 15; break; // norm=15, big=23, gap=1px case int n when(n == 16 || n == 17): spacing = 13; break; // norm=13, big=20, overlap=1px case int n when(n == 18 || n == 19): spacing = 11; break; // norm=11, big=17, overlap=3px case int n when(n == 20 || n == 21): spacing = 10; break; // norm=10, big=15, overlap=4px case int n when(n == 22 || n == 23): spacing = 9; break; // norm=9, big=14, overlap=5px case int n when(n == 24 || n == 25): spacing = 8; break; // norm=8, big=12, overlap=6px case int n when(n >= 26 && n <= 29): spacing = 7; break; // norm=7, big=11, overlap=7px case int n when(n >= 30 && n <= 33): spacing = 6; break; // norm=6, big=9, overlap=8px case int n when(n >= 34 && n <= 37): spacing = 5; break; // norm=5, big=8, overlap=9px case int n when(n >= 38 && n <= 49): spacing = 4; break; // norm=4, big=6, overlap=10px case int n when(n >= 50 && n <= 65): spacing = 3; break; // norm=3, big=5, overlap=11px case int n when(n >= 66): spacing = 2; break; // norm=2, big=3, overlap=12px default: spacing = 2; break; } // TODO: Draw background rectangle //g.FillRectangle(new SolidBrush(Color.FromArgb(71, 147, 31)), 0, 0, spacing * city.Food + 21 - spacing + 6, 23); // Background square for food //g.FillRectangle(new SolidBrush(Color.FromArgb(55, 123, 23)), x_size - (spacing * Math.Abs(city.SurplusHunger) + 21 - spacing + 3), // 0, spacing * Math.Abs(city.SurplusHunger) + 21 - spacing + 6, 23); // Background square for surplus/hunger // Icons for (int i = 0; i < city.Food; i++) { g.DrawImage(Images.CityFoodBig, i * spacing + 3, 15); } for (int i = 0; i < Math.Abs(city.SurplusHunger); i++) { if (city.SurplusHunger < 0) { g.DrawImage(Images.CityHungerBig, x_size - (spacing * Math.Abs(city.SurplusHunger) + 14 - spacing) + i * spacing, 15); // Hunger } else { g.DrawImage(Images.CityFoodBig, x_size - (spacing * Math.Abs(city.SurplusHunger) + 14 - spacing) + i * spacing, 15); // Surplus } } // TRADE // Text Draw.Text(g, $"Trade: {city.Trade}", _font, StringAlignment.Near, StringAlignment.Near, Color.FromArgb(239, 159, 7), new Point(0, 41), Color.Black, 1, 1); Draw.Text(g, $"Corruption: {city.Corruption}", _font, StringAlignment.Far, StringAlignment.Near, Color.FromArgb(227, 83, 15), new Point(225, 41), Color.Black, 1, 1); // Spacing between icons switch (city.Trade + city.Corruption) { case int n when(n >= 1 && n <= 15): spacing = 15; break; // norm=15, big=23, gap=1px case int n when(n == 16 || n == 17): spacing = 13; break; // norm=13, big=20, overlap=1px case int n when(n == 18 || n == 19): spacing = 11; break; // norm=11, big=17, overlap=3px case int n when(n == 20 || n == 21): spacing = 10; break; // norm=10, big=15, overlap=4px case int n when(n == 22 || n == 23): spacing = 9; break; // norm=9, big=14, overlap=5px case int n when(n == 24 || n == 25): spacing = 8; break; // norm=8, big=12, overlap=6px case int n when(n >= 26 && n <= 29): spacing = 7; break; // norm=7, big=11, overlap=7px case int n when(n >= 30 && n <= 33): spacing = 6; break; // norm=6, big=9, overlap=8px case int n when(n >= 34 && n <= 37): spacing = 5; break; // norm=5, big=8, overlap=9px case int n when(n >= 38 && n <= 49): spacing = 4; break; // norm=4, big=6, overlap=10px case int n when(n >= 50 && n <= 65): spacing = 3; break; // norm=3, big=5, overlap=11px case int n when(n >= 66): spacing = 2; break; // norm=2, big=3, overlap=12px default: spacing = 2; break; } // TODO: Draw background rectangle //g.FillRectangle(new SolidBrush(Color.FromArgb(71, 147, 31)), 0, 0, spacing * foodIcons + 21 - spacing + 6, 23); //background square for food //g.FillRectangle(new SolidBrush(Color.FromArgb(55, 123, 23)), x_size - (spacing * Math.Abs(surplusIcons) + 21 - spacing + 3), 0, spacing * Math.Abs(surplusIcons) + 21 - spacing + 6, 23); //background square for surplus/hunger // Icons for (int i = 0; i < city.Trade; i++) { g.DrawImage(Images.CityTradeBig, i * spacing + 3, 56); } for (int i = 0; i < city.Corruption; i++) { g.DrawImage(Images.CityCorruptBig, x_size - (spacing * city.Corruption + 14 - spacing) + i * spacing, 56); } // TAX+LUX+SCI // Text Draw.Text(g, $"50% Tax: {city.Tax}", _font, StringAlignment.Near, StringAlignment.Near, Color.FromArgb(239, 159, 7), new Point(0, 95), Color.Black, 1, 1); Draw.Text(g, $"0% Lux: {city.Lux}", _font, StringAlignment.Center, StringAlignment.Near, Color.White, new Point(111, 95), Color.Black, 1, 1); Draw.Text(g, $"50% Sci: {city.Science}", _font, StringAlignment.Far, StringAlignment.Near, Color.FromArgb(63, 187, 199), new Point(225, 95), Color.Black, 1, 1); // Spacing between icons switch (city.Tax + city.Lux + city.Science) { case int n when(n >= 1 && n <= 15): spacing = 15; break; // norm=15, big=23, gap=1px case int n when(n == 16 || n == 17): spacing = 13; break; // norm=13, big=20, overlap=1px case int n when(n == 18 || n == 19): spacing = 11; break; // norm=11, big=17, overlap=3px case int n when(n == 20 || n == 21): spacing = 10; break; // norm=10, big=15, overlap=4px case int n when(n == 22 || n == 23): spacing = 9; break; // norm=9, big=14, overlap=5px case int n when(n == 24 || n == 25): spacing = 8; break; // norm=8, big=12, overlap=6px case int n when(n >= 26 && n <= 29): spacing = 7; break; // norm=7, big=11, overlap=7px case int n when(n >= 30 && n <= 33): spacing = 6; break; // norm=6, big=9, overlap=8px case int n when(n >= 34 && n <= 37): spacing = 5; break; // norm=5, big=8, overlap=9px case int n when(n >= 38 && n <= 49): spacing = 4; break; // norm=4, big=6, overlap=10px case int n when(n >= 50 && n <= 65): spacing = 3; break; // norm=3, big=5, overlap=11px case int n when(n >= 66): spacing = 2; break; // norm=2, big=3, overlap=12px default: spacing = 2; break; } // TODO: Draw background rectangle //g.FillRectangle(new SolidBrush(Color.FromArgb(71, 147, 31)), 0, 0, spacing * foodIcons + 21 - spacing + 6, 23); //background square for food //g.FillRectangle(new SolidBrush(Color.FromArgb(55, 123, 23)), x_size - (spacing * Math.Abs(surplusIcons) + 21 - spacing + 3), 0, spacing * Math.Abs(surplusIcons) + 21 - spacing + 6, 23); //background square for surplus/hunger // Icons for (int i = 0; i < city.Tax; i++) { g.DrawImage(Images.CityTaxBig, i * spacing + 3, 80); } for (int i = 0; i < city.Science; i++) { g.DrawImage(Images.CitySciBig, x_size - (spacing * city.Science + 14 - spacing) + i * spacing, 80); } for (int i = 0; i < city.Lux; i++) { g.DrawImage(Images.CityLuxBig, x_size / 2 - (spacing * city.Lux + 14 - spacing) / 2, 80); } // SUPPORT+PRODUCTION // Text Draw.Text(g, $"Support: {city.Support}", _font, StringAlignment.Near, StringAlignment.Near, Color.FromArgb(63, 79, 167), new Point(0, 135), Color.Black, 1, 1); Draw.Text(g, $"Production: {city.Production}", _font, StringAlignment.Far, StringAlignment.Near, Color.FromArgb(7, 11, 103), new Point(225, 135), Color.Black, 1, 1); // Spacing between icons switch (city.Support + city.Production) { case int n when(n >= 1 && n <= 15): spacing = 15; break; // norm=15, big=23, gap=1px case int n when(n == 16 || n == 17): spacing = 13; break; // norm=13, big=20, overlap=1px case int n when(n == 18 || n == 19): spacing = 11; break; // norm=11, big=17, overlap=3px case int n when(n == 20 || n == 21): spacing = 10; break; // norm=10, big=15, overlap=4px case int n when(n == 22 || n == 23): spacing = 9; break; // norm=9, big=14, overlap=5px case int n when(n == 24 || n == 25): spacing = 8; break; // norm=8, big=12, overlap=6px case int n when(n >= 26 && n <= 29): spacing = 7; break; // norm=7, big=11, overlap=7px case int n when(n >= 30 && n <= 33): spacing = 6; break; // norm=6, big=9, overlap=8px case int n when(n >= 34 && n <= 37): spacing = 5; break; // norm=5, big=8, overlap=9px case int n when(n >= 38 && n <= 49): spacing = 4; break; // norm=4, big=6, overlap=10px case int n when(n >= 50 && n <= 65): spacing = 3; break; // norm=3, big=5, overlap=11px case int n when(n >= 66): spacing = 2; break; // norm=2, big=3, overlap=12px default: spacing = 2; break; } // TODO: Draw background rectangle //g.FillRectangle(new SolidBrush(Color.FromArgb(71, 147, 31)), 0, 0, spacing * foodIcons + 21 - spacing + 6, 23); //background square for food //g.FillRectangle(new SolidBrush(Color.FromArgb(55, 123, 23)), x_size - (spacing * Math.Abs(surplusIcons) + 21 - spacing + 3), 0, spacing * Math.Abs(surplusIcons) + 21 - spacing + 6, 23); //background square for surplus/hunger // Icons for (int i = 0; i < city.Support; i++) { g.DrawImage(Images.CitySupportBig, i * spacing + 3, 121); } for (int i = 0; i < city.Production; i++) { g.DrawImage(Images.CitySupportBig, x_size - (spacing * city.Production + 14 - spacing) + i * spacing, 121); } } return(icons); }
// Draw resource map public static Bitmap CityResourcesMap(City city, int zoom) { var map = new Bitmap(4 * 8 * (8 + zoom), 4 * 4 * (8 + zoom)); using (var g = Graphics.FromImage(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 = Map.TileC2(newX, newY).Graphic.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.ActiveCiv) && (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); }
private void MapPanel_Paint(object sender, PaintEventArgs e) { // Title using var _font = new Font("Times New Roman", 17, FontStyle.Bold); Draw.Text(e.Graphics, $"{Game.PlayerCiv.Adjective} Map", _font, StringAlignment.Center, StringAlignment.Center, Color.FromArgb(135, 135, 135), new Point(Width / 2, 20), Color.Black, 1, 1); }