2D Map Generation: Height Map Generator - Evaluation

Started by
6 comments, last by Green_Baron 5 years, 1 month ago

For this I've used Godot Engine and GDScript.


Hello, I am working in a Map Generation project, and I am trying to come up with a Height Map generator for the hills and mountain-ranges. I'm pretty amateur when it comes to programming in general and I mostly try to make everything from zero as I don't know much about game theory or any big programming techniques, so forgive me if anything I've done is ugly or goes totally against any common sense.

Up until now, I've come up with this:


extends Node2D

export(int) var Origin_Min
export(int) var Origin_Max
export(int) var Power

var HeightMap = {}

func _ready():
	new_seed()
	_mountain_range()

func new_seed():

	randomize()
	var random_seed = randi()
	seed(random_seed)
	print(random_seed)


func _mountain_range():

#ORIGINS PHASE - set's origin points for the mountain-ranges
	var OriginList = {}
	for origin in round(rand_range(Origin_Min, Origin_Max)):

		var originPointX = round(rand_range(1, 126))
		var originPointY = round(rand_range(1, 126))
		if OriginList.has(Vector2(originPointX, originPointY)):

			continue
		OriginList[Vector2(originPointX, originPointY)] = {"Power": round(rand_range(1, 5)), "Connected": false}
		HeightMap[Vector2(originPointX, originPointY)] = 3
		$TileMap.set_cellv(Vector2(originPointX, originPointY), 2)

#MOUNTAIN-RANGES PHASE - try to draw mountain_ranges between every origin based on their Power level
	for origin in OriginList:

		for point in OriginList:

			if OriginList[point].Connected:

				continue
			if round(origin.distance_to(point)) <= (OriginList[origin].Power * Power) and round(origin.distance_to(point)) != 0:

				var current = origin
				while current != point:

					var currentDist = round(current.distance_to(point))
					var closerDist = []
					var sameDist = []
					for direction in dir.Directions:

						var step = Vector2(clamp(current.x + direction.x, 1, 126), clamp(current.y + direction.y, 1, 126))
						if step == point:

							OriginList[origin] = {"Power": round(rand_range(2, 3)), "Connected": true}
							current = point
							break
						if round((step).distance_to(point)) <= currentDist:

							closerDist.append(step)
						if round((step).distance_to(point)) >= currentDist:

							sameDist.append(step)
					if round(rand_range(0, 10)) >= 3 and closerDist.size() >= 1: #70% chance of going closer

						current = closerDist[round(rand_range(0, clamp(closerDist.size() - 1, 0, 3)))]
						HeightMap[current] = round(rand_range(2, 3))
						$TileMap.set_cellv(current, 2)
					elif sameDist.size() >= 1: #30% chance of taking a variation

						current = sameDist[round(rand_range(0, clamp(sameDist.size() - 1, 0, 3)))]
						HeightMap[current] = round(rand_range(2, 3))
						$TileMap.set_cellv(current, 2)

#FILL UP PHASE - fill up the rest of the map with height level 0 tiles
	var xCoord = 0
	var yCoord = 0
	for tile in 16384:

		if not HeightMap.has(Vector2(xCoord, yCoord)):

			$TileMap.set_cellv(Vector2(xCoord, yCoord), 0)
		xCoord += 1
		if xCoord == 128:

			xCoord = 0
			yCoord += 1

This code is divided in three parts:

  1. Set a random number of origins in random locations(excluding borders) and give these origins a power level.
  2. For each origin, check if it can "link" with each other origin based in its power level, if so, "draw" a mountain-range in between them.
  3. Draw the rest of the map.

The result is this:

Godot_v3.1-stable_win64_2019-07-01_02-58-23.png.a30c5d4dd5eb040fe377d956168b27f5.png

(can have other results because of seed)

I rarely have some random problems with this code, like an origin point that says that it is nor closer nor at the same distance as another origin point when they are drawing a mountain-range in between them.

Advertisement

Haven't looked in detail, looks like in some cases the initial points are just too random to be connectable.

Usually, people tackle this either with a function that produces a reproducible and coherent result (like Perlin noise and all its derivatives and versions for example) or by modelling processes from nature (like hydrology or tectonics). I am specifically interested in the latter.

Sorry if i can't be more helpful. I personally haven't tackled that yet, but it is on my list ?

Interesting. I've just downloaded both articles and took a look at them. It's pretty much what I intended to do, but I really didn't want to use Perlin Noise for it. In fact I wanted to hardcode the rules for the map generation, like, every detail. For example: Trees becoming more sparse the closer to the higher areas, for each level of height, a different rand_range(), so they wouldn't be spread in a deterministic pattern and more in a range of random ranges. The same for rivers, and other plant life and also animal life spawns. There's really nothing specific about Perlin Noise that I dislike, the thing is that I don't even know how to implement that and if I knew, I probably wouldn't know how to modify it to suit my needs.

 

Hey, do you know where could I search more articles like those two? They really drew my attention, thank you for those! I am really into reading more things like them. You helped a lot!

I am not a skillful programmer.

First i would concentrate on finding the surface of the landscape, afterwards on scattering veneer. I see the latter as a minor problem, compared to the former. For example, once we have a surface, we could filter out parts with a certain slope and height through vertical projection. These parts then get a representative cover. Climate regions could be simulated by shifting the regions up and down.

But there are a whole lot of cookbooks for perlin noise generators. One of many examples. On the vterrain.org page there is a link to a work that uses a sketch as a seed and modifier for perlin noise generated, naturally looking landscape. It is not difficult to make noise.

You asked for more links, if you approach the problem from the computer side then said vterrain.org might help, or siggraph papers. Am sure there are others. If you come from the geoscience side, it quickly gets overwhelmingly complicated. Much work on simulations and modelling is published by the EGU, AGU, in journals like Nature and Science, Elsevier journals, by a plethora of national and international organisations like geological surveys and weather services. I think it might be worth to have a look at what the professionals do to simulate erosion and weathering, or landscape and plant cover change.

And Of course one can always download dem (digital elevation model) data from the internet.

I wrote this for moderately experienced programmers but it more inspirational than how to: http://www.vrmmorpgordie.com/

For rivers, I am currently writing up my latest system which is better.

 

Cool, thanks ! Will read later ?

Edit: i looked over it. Very thorough work ! Almost seems like i come too late ?

 

Another how to on making noise: https://flafla2.github.io/2014/08/09/perlinnoise.html

Unfortunately there are no howto's i know of on modelling physical processes. Too complicated. But a lot of papers. The linked hydrology is a start imo, but has its flaws from a geoscience point of view. For example, river mouths should be the outcome of modelling, not initial data.

I am tempted to write together a sermon how mountains form and weather away these days, from a high level overview, but that'll take too much time and space i need for other tasks right now. A lookup list for the eager: modern style plate tectonics, wilson cycle, middle oceanic ridge, converging plates, continental and oceanic crust, active continental margin, density driven subduction, slab tear-off and orogeny, uplift and subsidence, physical, chemical and biological weathering, river systems and sediment transport. If we can find an integration, we'd submit a paper for review ?

 

I started collecting information for the next step of my project and realized that there is really amazing work on bringing some sort of realism to procedural terrain generation out there. I post it, maybe it is of interest.

Examples:

http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/

or something more modern:

http://procworld.blogspot.com/2016/04/geometry-is-destiny.html

or:

http://procworld.blogspot.com/2019/04/moonmaker.html

 

I think i abandon the noise idea in favour of one of those modelling techniques.

Will continue to search.

 

This topic is closed to new replies.

Advertisement