Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am programming a tile based game and I have some basic tiles (grass, dirt, etc..), but I can't figure out how to make good random map generation, because when I do some really random selection, if the tile should be grass/dirt, I get this:

In-game picture

I understand why this is happening, but what I want is to create some random continuous areas of grass or dirt. Something that would make more sense, like this:

Desired result

share|improve this question
1  
In addition to the proposed answers, you could write your own cellular automaton engine to generate such maps. Modifying the rules of the automaton you could generate very different behaviours, leading in very different types of maps. For example, gievn a 2d automaton similar to Life, flooding rules could lead to "ocean and isles" (Like your picture above), and a rule like 1267/17 could lead into beautiful laberynths. –  Manu343726 Jun 22 at 17:16

4 Answers 4

up vote 12 down vote accepted

What you could do is randomly generate a Voronoi map like this:

  1. Picking random center points (see the black dots) and randomly decide if they are grass or dirt.
  2. Then for over all tiles, check if it's closest to a center point of dirt or a grass.
  3. Done!

If what you did previously is "flip a coin" for each tile (noise), generating a Voronoi diagram will provide a much better result.

You could improve on this by dividing the center points into islands with an algorithm that:

  1. Picks a small group of centers points and designates them as leaders.
  2. Iteratively adds a random adjacent undecided center point each turn.
  3. Done!

enter image description here

share|improve this answer
1  
Thanks, but it seems like a very difficult solution. –  ViliX64 Jun 21 at 10:21
    
This is not a very difficult solution. First randomly pick the center points. Then decide if they are grass or dirt. Now loop over the array and decide if each tile is closest to a dirt point or a grass point. Perhaps tell me which part challenging? –  Zehelvion Jun 21 at 10:33
    
Measuring the distance. Anyway, I will try and let you know. –  ViliX64 Jun 21 at 10:55
    
Ok, so I have succesfully generated some points. (dropbox.com/s/dlx9uxz8kkid3kc/random_tile_map2.png) and so my whole class for generating looks like this: dropbox.com/s/pxhn902xqrhtli4/gen.java. But it still doesn't work. –  ViliX64 Jun 21 at 11:07
1  
@ViliX your links are broken –  Artur Czajka Jul 3 at 13:13

You could use perlin noise, which is normaly used for heightmap generation. Perlin noise in games

Then you could use the heights as an adviser, how high the chance of grass/dirt occuring in one region of the map is.

Example (Perlin noise values from 0-256): If the value is over 200 the chance that grass is placed is 80% (dirt 20%). If the value is between 100 and 200 the chance that grass is placed is 50% (dirt also 50%). If the value is under 100 the chance that grass is placed is 20% (dirt 80%).

share|improve this answer
    
Ok, let's say that I have an array[][] of float (0-1 of probability) and I can use it to spawn tiles with the probability. But how do I fill this probability array? The array is (let's say) 400x200, how to fill it with probability values? –  ViliX64 Jun 21 at 10:17
    
He is suggesting to fill it with perlin noise (instead of white noise like coin flips). –  Zehelvion Jun 21 at 10:24
    
Yes, but how can I achieve that? –  ViliX64 Jun 21 at 10:25
    
The link I posted could clear this question. First generate a noise and then smooth this noise.The result will be a 2 dimensional array you can use for further generation of the tilemap.link –  Klitz Jun 21 at 10:26
    
Ok, thanks for your anwser. –  ViliX64 Jun 21 at 10:29

Select a point on the map. Place desired tile type with a base value such as 40. Keep track of where you placed your newly desired tile. Add the starting point to a list.

For each point in this list, you visit all neighbours. While you have enough power left (started at 40) add a desired tile and add it to the list to be visited. Give the new tile less power, determined by you. Easiest = random lowering. After you visited the tile from the list, remove it. Start over again by visiting any unvisited but created tiles.

share|improve this answer
1  
That seems like a good solution, thanks. –  ViliX64 Jun 21 at 10:04

enter image description here

http://gamedevelopment.tutsplus.com/tutorials/generate-random-cave-levels-using-cellular-automata--gamedev-9664

private int GetAdjacentCount(List<bool> list, Vector2 p)
{
    int count = 0;
    for (int y = -1; y <= 1; y++)
    {
        for (int x = -1; x <= 1; x++)
        {
            if (!((x == 0) && (y == 0)))
            {
                Vector2 point = new Vector2(p.x + x, p.y + y);
                if (PathFinder.Instance.InsideMap(point))
                {
                    int index = PathFinder.Instance.TileIndex(point);
                    if (list[index])
                    {
                        count++;
                    }
                }
                else
                {
                    count++;
                }
            }
        }
    }
    return count;
}
private List<bool> GetCellularList(int steps, float chance, int birth, int death)
{
    int count = _width * _height;
    List<bool> list = Enumerable.Repeat(false, count).ToList();
    for (int y = 0; y < _height; y++)
    {
        for (int x = 0; x < _width; x++)
        {
            Vector2 p = new Vector2(x, y);
            int index = PathFinder.Instance.TileIndex(p);
            list[index] = Utility.RandomPercent(chance);
        }
    }
    for (int i = 0; i < steps; i++)
    {
        var temp = Enumerable.Repeat(false, count).ToList();
        for (int y = 0; y < _height; y++)
        {
            for (int x = 0; x < _width; x++)
            {
                Vector2 p = new Vector2(x, y);
                int index = PathFinder.Instance.TileIndex(p);
                if (index == -1) Debug.Log(index);
                int adjacent = GetAdjacentCount(list, p);
                bool set = list[index];
                if (set)
                {
                    if (adjacent < death)
                        set = false;
                }
                else
                {
                    if (adjacent > birth)
                        set = true;
                }
                temp[index] = set;
            }
        }
        list = temp;
    }
    if ((steps > 0) && Utility.RandomBool())
        RemoveSmall(list);
    return list;
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.