// 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);
        }
Пример #3
0
 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);
 }