Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Random World Generation

I'm trying to find out a good way to create a method that generates a large world of tiles and objects, where the method itself only takes two parameters: width and height in tiles.

What I want to do, is split the map into "zones" with random sizes picked out from a width and height table using a random seed index. These zones gets a random biome to accompany it. I've been trying various things, and this is the closest I've become:
Code:
        public static World Generate(int width, int height)

        {

            // Create a new world

            World world = new World();

 

            // Generate a random generator

            Random rand = new Random();

 

            // Set the coordinates

            int x = 0, y = 0; string biome, image;

            // Until the X and Y values are outside the map: generate

            while (y < height)

            {

                // Create a seed for randomization (from 0 up to 9)

                int seed = rand.Next(10);

                // Split the map into zones of sizes based on the seed

                int zoneWidth = Widths[seed], zoneHeight = Heights[seed];

 

                // Get biome

                biome = Biomes[rand.Next(Biomes.Length)];

 

                // Cover area in tiles

                int row, col;

                for (int cy = 0; cy < zoneHeight; cy++)

                {

                    // Set new row and column hvalues

                    row = 1 + rand.Next(5);

                    col = 1 + rand.Next(6);

                    for (int cx = 0; cx < zoneWidth; cx++)

                    {

                        // Add landmarks in the middle of zones

                        if (cx == zoneWidth / 2 && cy == zoneHeight / 2)

                            world.Landmarks.Add(new Landmark(biome, x, y));

 

                        // Randomize ground tiles slightly

                        image = cx % rand.Next(5, 15) == 0 ? 

                            biome + "_Ground" : biome + "_GroundSpecial";

 

                        // Place ground tile only if within bounds of world

                        if (x < width && y < height)

                        {

                            // Place tile

                            world.Ground.Add(new Tile(image, x, y));

 

                            // Scenery placements (somewhat randomly)

                            if (cx % col == 0 && cy % row == 0)

                            {

                                int r = rand.Next(Scenery.Biome(biome).Count);

                                world.Sceneries.Add(Scenery.Get(Scenery.Biome(biome)[r],

                                    new Vector2(x, y)));

                            }

                            x++;

                        }

                        else if (x >= width)

                            x = 0;

                    }

                    y++;

                }

            }

 

            Console.WriteLine(world.Ground.Count);

 

            // Return the world

            return world;

        }

So when I try to create a world with the sizes 2048 x 2048, it should give me 4194304 tiles, but it gives me about 10 times less than the expected amount (at the console line), and it looks like it skips all but the first Y-axis of each zone. I don't know why, because if I output the X and Y values every time it adds a tile, it shows correct values from start to finish, but still only gives me around 400k tiles in the final list.

It might just be an obvious code mistake, but I don't see it right now. Anyone have a better algorithm or any idea what happens wrong with this code?

Any help is greatly appreciated! Thanks!
 
I noticed that I have to reset the X back to 0 every time the Y updates, so I added this line and now it's working to some extent. It's still not adding as many tiles as expected, though, so that is still up D:
 
well im no scripter, obviously, but it may be a problem with the different tileset pattern. could it be, that it counts ground, water and stuff like this not as a actual maptile?
 
I'm not using a tileset, and as stated in the second post, it creates most of the zones, but skips a few zones. Some coordinate issues here, not the tile collection. It's how the X and Y variables are handled.
Code:
public static World Generate(int width, int height)

        {

            // Create a new world

            World world = new World();

 

            // Generate a random generator

            Random rand = new Random();

 

            // Create a seed for randomization (from 0 up to 9)

            int seed = rand.Next(Widths.Length);

 

            // Set the coordinates

            int x = 0, y = 0, i = 0, b = rand.Next(Biomes.Length), leftX = 0, leftY = 0; string biome, image;

            int zoneHeight = Heights[seed]; bool noreset = false;

            // Until the X and Y values are outside the map: generate

            while (y < height)

            {

                // Create a seed for randomization (from 0 up to 9)

                seed = rand.Next(Widths.Length);

                // Split the map into zones of sizes based on the seed

                int zoneWidth = Widths[seed];

 

                // Set biome

                b++; noreset = false;

                if (b == Biomes.Length) b = 0;

 

                // Get biome

                biome = Biomes[b];

 

                // Add zone

                world.Zones.Add(new Zone(biome, x, y, zoneWidth, zoneHeight));

 

                // Cover area in tiles

                int col;

                for (int cy = 0; cy < zoneHeight; cy++)

                {

                    // Set new row and column hvalues

                    col = 10 + rand.Next(20);

                    for (int cx = 0; cx < zoneWidth; cx++)

                    {

                        // Randomize ground tiles slightly

                        image = cx % rand.Next(5, 15) == 0 ?

                            biome + "_GroundSpecial" : biome + "_Ground";

 

                        // Place ground tile only if within bounds of world

                        if (x < width && y < height)

                        {

                            // Place tile

                            world.Zones[i].Tiles.Add(new Tile(image, x, y));

 

                            // Scenery placements (somewhat randomly)

                            if (cx % col == 0 && cx != 0)

                            {

                                int r = rand.Next(Scenery.Biome(biome).Count);

                                world.Zones[i].Sceneries.Add(Scenery.Get(Scenery.Biome(biome)[r],

                                    new Vector2(x, y)));

                            }

                            x++;

                            if (x >= width)

                                break;

                        }

                        else if (x >= width)

                            break;

                    }

                    if (x >= width)

                    {

                        x = 0; leftX = 0;

                        leftY += zoneHeight;

                        noreset = true;

                        break;

                    }

                    x = leftX;

                    y++;

                }

                if(!noreset)

                    leftX += zoneWidth;

                x = leftX;

                y = leftY;

                i++;

            }

 

            Console.WriteLine(world.Zones.Count);

 

            // Return the world

            return world;

        }
This is the new method. In some cases it skips a few X-values on the second zone row.
If we assume a world made out of 2048 x 2048 tiles, and we have 20 zones per row, the first zone on the second row is kind of ignored and leaves an annoying empty hole.

I do not have performance issues with my tile iterations now that I split the zones into its own classes, only iterating tiles when the zone is within the screen bounds, but I am still trying to wrap my head around the black holes that randomly spawn. Perhaps someone can see a flaw in my code where it handles the X values that makes it skip some X-coordinates after moving to the next row?
 
rosareven":3ka508vq said:
May I ask how did you solve the issue, so that others who happen to have the same problem can learn from what you did?
Kind of late reply, I apologize for not being available for a long time. The code that was solved in this scenario is very old code and probably isn't very effective, but here's the code that was final after the solution was given.

Code:
// Zone Sets

        static int[] Widths = new int[] { 64, 48, 32 };

        static int[] Heights = Widths.Reverse<int>().ToArray();

 

        // Biomes

        static string[] Biomes = new string[] { "Forest", "Desert", "Snow", "Ash", "Lava", "Corruption", "Wasteland" };

 

        public static World Create(int width, int height)

        {

            // Create new world

            World world = new World();

            world.Width = width; world.Height = height;

 

            // Create a random generator

            Random rand = new Random();

 

            // Create a map seed (for randomization)

            int seed;

 

            // Biome index

            int biomeIndex = rand.Next(Biomes.Length);

 

            // Temporary veriables

            int x, y = 0, zoneHeight = 0, zoneWidth;

            bool newRow = true; int originX = 0, originY = 0;

 

            // While the Y-row is less than height

            while (y < height)

            {

                // Create new seed

                seed = rand.Next(Widths.Length);

 

                // If new row: set new height

                if (newRow)

                {

                    originY += zoneHeight;

                    originX = 0;

                    zoneHeight = Heights[seed];

                    newRow = false;

                }

 

                // Set zone width

                zoneWidth = Widths[seed];

 

                // Set X and Y

                x = originX; y = originY;

 

                // Get biome and fix index

                string biome = Biomes[biomeIndex]; biomeIndex++;

                if (biomeIndex == Biomes.Length) biomeIndex = 0;

 

                // Add zone

                world.Zones.Add(new Zone(biome, x, y, zoneWidth, zoneHeight));

 

                // Fix origin X

                originX += zoneWidth;

 

                // Check for new row

                if (originX >= width) newRow = true;

            }

 

            // Return the final world

            return world;

        }
I'm unaware of what actual change that was made, but this shows all the necessary data needed to understand what I actually did.
Random biome widths, random biome choices, and random landmarks (objects such as trees etc) in each biome.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top