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.
Generating heightmaps using particle deposition
Using Gaussian blurring on heightmaps
UPDATE: I published a part 2 to this article: Generating Lake and Rivers.
UPDATE: I published a part 3 to this article: Cities, caves and snow.
Hello, I have been looking for a great way to randomly generate a world and you really helped me! I have learned a lot but I still don’t know how you made a height map. If you could make some code or just explain it for me to understand would really help, Thanks!
Hi,
Since I originaly wrote this post, I have open sourced all of this project’s code on GitHub under the very permissive MIT license. You can find it here: https://github.com/gilles-leblanc/gameproject.
The code specific to world generation is in this folder: https://github.com/gilles-leblanc/gameproject/tree/master/MapGenerator.
You can even make it run for yourself (provided you have all the necessary dependencies (sorry no bundler yet)).
To run it, run map_output.rb and be prepared to wait a bit for the world to generate itself. You can configure everything with height_map_configurator.
To learn more about the technique I used to generate the heightmaps (all the source code is there, just in case you want additional explanations) you can read the following posts from my blog:
https://gillesleblanc.wordpress.com/2012/08/22/generating-heightmaps-using-particle-deposition/
https://gillesleblanc.wordpress.com/2012/08/24/using-gaussian-blurring-on-heightmap/
In addition be sure to check part II and part III from this series which you can find links to at the end of this blog post just above. These parts talk about how I generated rivers and lakes and how I choose where to place caves and cities.
In the code on GitHub, roads are also generated if certain conditions are met (not discussed in a blog post). Basically the conditions relate to the distance and position of the different cities that have been placed on the map.
Hope this helps !
Thank you for your great article. By the way, what kind of version of ruby do you use? I have some trouble with installing texplay.
I don’t recall the Ruby version for sure as this was years ago but I think it was 2.1.
I remember there was a problem with getting texplay working. It wasn’t working because of a compatibility issue, I had forked the repo (https://github.com/gilles-leblanc/texplay/tree/ruby21compat) and created a fix that I had submitted as a pull request to the main texplay project (https://github.com/banister/texplay/pull/25).
This had fixed it, but I haven’t followed anything Ruby related for years so it may have gotten broken again?
Can the result of the generated map be created as a text file using only the basic library of Ruby? I’d like to make a kind of command line utility. (If possible, could you please make command line version of this map generator?)
It could be generated as a text file.
I won’t be making it myself though as I haven’t touched this project or Ruby for that matter for years.
I’m just wandering that how did you generate a simple map with Ruby..
Apart from this blog post you can also find my other explanations on the two linked post at the bottom of my post.
Also, in my reply to the comment by Matthew Schmidt, I linked the github repo with all the source code.