I wanted to create a program that generates a random 2d world map. Like one you would find in old rpg video games. This got me to investigate the wonderful world of procedural content generation.
The word random is used here to mean that the map will be created using a certain amount of randomness so as to get a different map every time we generate one.
Using totally random data would just create a bunch of noise. I generated a map using totally random data to show you what I mean.
I looked into how to create random 2d worlds. My research on Google led me to pseudo-random number generation and Perlin noise. I quickly realized this wasn’t the path I wanted to investigate.
I wanted to share with you the solution I adopted. It’s easy to code and powerful. I ended up generating a heightmap. These are primarily used to create 3d worlds, but when you think about it, it’s even easier to use them for a 2d world by applying some sort of filter on the height values of the map to convert them to 2d tiles. Here is some code that uses an already generated heightmap, of exactly the same kind you would use for 3d graphics, and turns it in a 2d world map.
require '../map' require '../tile' require './height_map' class WorldMap < Map def initialize(width, height, height_map) super(width, height) (0...width).each do |x| (0...height).each do |y| # If the tile is on the edge of the map I select a water tile whatever the results. This is because I absolutely wanted to create an island. If this is not your goal you can forgo this. if edge_of_map?(x, y) terrain = :water elsif height_map[x + y * width] == 0 terrain = :water elsif height_map[x + y * width] >= 70 terrain = :mountain elsif height_map[x + y * width] >= 1 && height_map[x + y * width] <= 2 terrain = :sand elsif height_map[x + y * width] >= 30 && height_map[x + y * width] <= 60 terrain = :forest else terrain = :grass end @tiles[x + y * width] = Tile.new(terrain, x, y) end end end end
This will allow us to generate something like this:
Bear in mind that these are preliminary results. I still have much work to do on the height map generator to get the kind of results I am looking for.
Generating a heightmap is actually pretty simple. You can look up my two previous posts on the subject for more information.