Hello,
There's been a while since I don't post here at OTLand.
Last week I've decided to research a subject that has been my interest for years: pseudo-random map generation.
This weekend I've made the first prototype:
I've chosen Remere's Mapeditor as the base code because it already has proper map editing functions and will reduce a lot of work related to map viewing, editing, automatic borders and more. The main subject here is pseudo-random, not map editing.
The goal of this first attempt was to generate a simple island.
My research began with the Perlin Noise, which I knew it was used by other game developers to generate pseudo random levels.
This repository saved me some time because it has a single header implementation of perlin noise that could be easily integrated to Remere.
By inputing a XY coordinate value to the noise function, we get a 0 to 1 value which is random, but not completely random. Changing the seed, usually using current time in seconds, we get new values for the noise function.
The first code was really simple. A 100x100 grid which each tile was assigned a noise value from 0 to 1.
Using a simple rule, we can decide what should be the ground ID for each tile.
If we think that noise is the terrain elevation and 0.3 means the sea level, we could say:
0.0 <= noise < 0.3 means 'water'
0.3 <= noise < 0.8 means 'grass'
0.8 <= noise < 1.0 means 'mountain'
Using the Remere's borderize function I thought that the first result would show something nice.
But it was garbage.
So I've added a simple window so I could play with the noise parameters.
X and Y are the top left coordinates where the map will be generated.
Width and Height are the size of the generated map.
Scale is a factor multiplied by each tile coordinate. We could say that this is the noise frequency value.
Octaves are the number of times that the noise function is called.
After some fine tuning on parameters, it improved quite a bit.
But it still doesnt look like an island. It's more like a clip from a big continent.
Thinking about an island:
- It's surrounded by water (low heights there)
- The middle of it has land, and maybe some mountains (high heights)
So, in addition to the noise, another math function could be added.
The map center is located at:
centerX = left + width / 2
centerY = top + height / 2
The radius of the island could fill the whole generated map area, so:
radius = width / 2.
So for every tile, we'd like to reduce the height value if it's far from the center and increase it near the center.
heightIncrease = 1 - distance to center / radius
Adding it to the height generated by the noise function, we start to get some nice results, which are shown in the video.
This is it for this post. I'm not sure if I'll continue researching this as it's just a hobby for now.
The goal here is not to replace the mapper, but just aid the development of new maps.
For the next post I'll probably try to generate the path of hunting caves.
There's been a while since I don't post here at OTLand.
Last week I've decided to research a subject that has been my interest for years: pseudo-random map generation.
This weekend I've made the first prototype:
I've chosen Remere's Mapeditor as the base code because it already has proper map editing functions and will reduce a lot of work related to map viewing, editing, automatic borders and more. The main subject here is pseudo-random, not map editing.
The goal of this first attempt was to generate a simple island.
My research began with the Perlin Noise, which I knew it was used by other game developers to generate pseudo random levels.
This repository saved me some time because it has a single header implementation of perlin noise that could be easily integrated to Remere.
By inputing a XY coordinate value to the noise function, we get a 0 to 1 value which is random, but not completely random. Changing the seed, usually using current time in seconds, we get new values for the noise function.
The first code was really simple. A 100x100 grid which each tile was assigned a noise value from 0 to 1.
Using a simple rule, we can decide what should be the ground ID for each tile.
If we think that noise is the terrain elevation and 0.3 means the sea level, we could say:
0.0 <= noise < 0.3 means 'water'
0.3 <= noise < 0.8 means 'grass'
0.8 <= noise < 1.0 means 'mountain'
Using the Remere's borderize function I thought that the first result would show something nice.
But it was garbage.
So I've added a simple window so I could play with the noise parameters.
X and Y are the top left coordinates where the map will be generated.
Width and Height are the size of the generated map.
Scale is a factor multiplied by each tile coordinate. We could say that this is the noise frequency value.
Octaves are the number of times that the noise function is called.
Gotta study more, but here're my thoughts for now:
From what I've seen octaves gives how much detail the noise has. It reminds me of the Fourier Series.
So, the first time the noise function is called, it has a small frequency and high amplitude. This gives us the bottom of the sea and high ground terrains.
As we advance on the octaves, we get smaller amplitudes, but higher frequencies. This way we get the detail on the bottom of the sea and on the high ground terrains.
From what I've seen octaves gives how much detail the noise has. It reminds me of the Fourier Series.
So, the first time the noise function is called, it has a small frequency and high amplitude. This gives us the bottom of the sea and high ground terrains.
As we advance on the octaves, we get smaller amplitudes, but higher frequencies. This way we get the detail on the bottom of the sea and on the high ground terrains.
After some fine tuning on parameters, it improved quite a bit.
But it still doesnt look like an island. It's more like a clip from a big continent.
Thinking about an island:
- It's surrounded by water (low heights there)
- The middle of it has land, and maybe some mountains (high heights)
So, in addition to the noise, another math function could be added.
The map center is located at:
centerX = left + width / 2
centerY = top + height / 2
The radius of the island could fill the whole generated map area, so:
radius = width / 2.
Thinking about it, probably using a smaller percentage of the width would give better results, as we'd have a larger portion of water, making the island to be 100% surrounded by water.
So for every tile, we'd like to reduce the height value if it's far from the center and increase it near the center.
heightIncrease = 1 - distance to center / radius
Adding it to the height generated by the noise function, we start to get some nice results, which are shown in the video.
This is it for this post. I'm not sure if I'll continue researching this as it's just a hobby for now.
The goal here is not to replace the mapper, but just aid the development of new maps.
For the next post I'll probably try to generate the path of hunting caves.
Attachments
-
1568082190331.png837.2 KB · Views: 31 · VirusTotal
Last edited: