Simple Map Generator Part 5 ( Moisture)

Hey hey!

So we’ve created rivers in last part right? Now that we have elevation and river , now we can calculate moisture which we’ll use for biomes later. I guess this will be a short post , since calculating moisture is pretty much same as calculating elevations. Pretty similar iterations , almost same.

The main idea here is to set river moisture a static value and then iterate through all corners and decrease this value as the corner gets further away from the river. Then we’ll also set center ( polygon ) moisture as the average of it’s corners’ moisture , easy peasy.

 

OK so I’ll start with our first method , CalculateCornerMoisture() }

 private void CalculateCornerMoisture()
{
    var queue = new Queue<Corner>();

    foreach (var q in App.AppMap.Corners.Values)
    {
        if ((q.Water || q.River > 0) && !q.Ocean)
        {
            q.Moisture = q.River > 0 ? Math.Min(3.0, (0.2 * q.River)) : 1.0;
            queue.Enqueue(q);
        }
        else
        {
            q.Moisture = 0.0;
        }
    }

    while (queue.Count > 0)
    {
        var q = queue.Dequeue();

        foreach (var r in q.Adjacents)
        {
            var newMoisture = q.Moisture * 0.9;
            if (newMoisture > r.Moisture)
            {
                r.Moisture = newMoisture;
                queue.Enqueue(r);
            }
        }
    }

    foreach (var q in App.AppMap.Corners.Values)
    {
        if (q.Ocean || q.Coast)
        {
            q.Moisture = 1.0;
        }
    }
}

As you can see we got 3 simple loops here. I won’t go into the detail as they are pretty much self explanatory.

First we iterate through all corners , set rivers moisture to 0.2 * river size ( maximum 3.0 ) and then add those river corners to the queue.

Then we start processing stuff in the queue , for each corner in the queue , we find it’s adjacent and set moisture to the 0.9 of original value. So with each step , moisture is decreased by 0.1 of the closest river moisture.

Then at last we set ocean and coast moisture to a standard value , 1.0.

I’m using a little different method in my personal project , merging 1st and 3rd loop together.

foreach (Corner q in App.AppMap.Corners.Values.Where(q => (q.Water || q.River > 0) && !q.Ocean))
{
    q.Moisture = q.Water
        ? 1
        : ( q.River > 0
            ? Math.Max(3.0, (0.2 * q.River))
            : 0.1 );
    queue.Enqueue(q);
}

It does pretty much the same thing , just in one loop and I don’t think setting ocean moistures before effects much or anything at all.

 

Anyway , once we set corner moisture…. actually we’re almost done.

Amit prefers to redistribute moistures as well ( remember we did the same thing for elevation before ) I personally prefer not to do this but here it is ;

private void RedistributeMoisture()
{
    var locations = App.AppMap.Corners.Values.OrderBy(x => x.Moisture).ToArray();

    for (int i = 0; i < locations.Count(); i++)
    {
        locations[i].Moisture = (float) i/(locations.Count() - 1);
    }
}

I added this to the sample solution below but it creates a very low moisture / desert-ish island for me at the moment , so it’ll be commented out. But remember all this stuff is just about some static variables. I know it’s a very bad practice but you’ll see magic numbers around , like 3.0 being the maximum river moisture , in that method above. All you have to do play with such numbers until you got an island you like.

 

One last thing before we finish , setting center ( polygon ) moistures. As I said before we’ll just take the average of corners and use it as center moisture , so it’s simple as this ,

foreach (Center c in App.AppMap.Centers.Values)
{
    c.Moisture = c.Corners.Sum(x => x.Moisture) / c.Corners.Count();
}

 

Aaand we’re done! Now when you run it , it should look something like this ,

WindowClipping (7)

 

Not bad eh? Well actually we’re pretty much done now , at least code-wise. There is only biome selection left and that’s not really a technical issue , also it’s in the sample solution since the Part 2 , as we needed to visualize it somehow. Still I may post about it in the future , or maybe some other stuff like the methods I used etc.

 

I really hope you liked it or at least found useful. I’m still working on this occasionally so I’ll probably post about it in the future again , maybe even about the XNA version of it.

 

You can find the sample solution file below , please don’t hesitate to contact me for any questions!

 

 

Visual Studio 2010 Solution

blog comments powered by Disqus