Random Map Generation | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Generating 2D height maps the easy way | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
by Matt "dxprog" Hackmann | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Introduction | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Generating random terrain for games like Civilization or Age of Empires has always intrigued me. How could they make a map that was random yet not a bunch of specs all over the place? Now, there’s probably as many ways to produce a good random map as there are grains of sand. Many of these include using fancy physics simulations, cellular automation, etc. These methods work well, but take time to program and time to produce. I’m not saying that these are bad as they offer more control of the terrain generated than my method, but if you just want something simple for a strategy game or basic terrain for a 3D game that’s easy to program and fairly quick for the computer to create then keep reading. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The Theory | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
My method for producing maps is pretty straight forward, no fancy math or AI to program. The whole system is based on averages. But enough of the talking, we'll get straight down to how it's done. It all starts out as a 2D array that is filled with random numbers (you could use a 1D array, but since this tutorial is about simplicity we'll go 2D). The dimensions are the size of your map. For our example I'll use a 5x5 map. The first step is to fill the entire array with random numbers. I prefer to use numbers between 1 and 255, but you could go as high as you want (if you are producing a height map image, stay within those limits).
Now comes the meat of the whole thing: For each cell we replace its value with the average value of all the cells around it. In the example the cell in question is in dark gray and all its neighboring cells are light gray:
So we average out the values in the light gray cells, which is 112 in this case, and replace the value in the dark gray cell with that value. We do this for every cell until the entire map is done.
And that's the hard part :-)! If you're just making a height map to be used in a 3D game, we're pretty much done, but if we're doing a 2D map continue reading (3D people should continue reading as a couple of extra tips that apply to you will be presented later). I should note that it would be wise to keep a running tally of the average for each cell. We will then average out this number to get the average number of all the cells (CellsAvg = TotalAvgs / (MapWidth * MapHeight)). This will be used to determine the land type which, in my example, consists of land and water. Basically we run through each cell again and if it's less than the cell average the cell is water, greater or equal to, land.
Now you could stop here and use what you've got, but by running the map through the routine a few more times you can get different (probably better) results. In the 3D realm this will result in less hilly terrain.
The more you run it through, the flatter the terrain gets making bigger islands in the 2D case. Now of course, you aren't limited to just land and water. With a little tweaking you can do mountains, deserts, etc. Essentially all you need to do is change the conditions that choose what's what. For example, in the example map below less than the CellAvg is water, grater or equal to this but less than (CellAvg + 20) is land, and everything above are mountains.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Tips | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3D Terrain Minimums and Maximums - For 3D terrain you can impose some minumums and maximums by adding or subtracting to the random value in each cell. Another Array - Using seperate arrays for the noise map and averaged map will lead to different, possibly better results. Play With It - What I have shown here barely scratches the surface of what you could do with this algorithm. Just try playing around with it and see what you come up with :-). |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Conclusion | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
I hope that you've learned something in this tutorial and that it will be useful for you. I have a ready-to-go example with VB source code so you can see this in action [Download]. If you have any comments, suggestions, etc. you can reach me at: Matt.Hackmann@gmail.com. Until next time, may the force of programming be with you :-). |