Three months passed since the previous post. Too much time and too less done for the period, but the work had never stopped. Going with the baby steps I have reworked some basic functional, including a heightmap generation I want to cover in this post.
I was quite happy with the heightmap and coastlines I got, but there were a couple of problems. The heightmap generation output was too uniform, all produced islands were perfectly fitted into a volcanic (high) island model, but islands could be not only volcanic. I have to re-visit the heightmap routine in order to add some variety. The solution is to create a couple of pre-made templates and apply them based on a random or user selection.
Another issue is a coastline and let’s start with it. I had too options there – curved and linear coastlines. Let’s take a look on the example from the initial post:
Linear variant works perfectly, but I don’t like its angularity. The curved coastline looks better, but it’s too smoothed and “vanished”. The real problem with this curved approach is that coastline got interpolated independently from the graph structure, so we see a curved coastline but actual graph is not changed. So to add any new visible element I have to consider both graph structure and rendered coastline. Frankly speaking, I do not know how to resolve it, but I can try to make a graph much more detailed along the coastline. In this case the real linear and approximate curved coastlines will be much closer to each other and the gap won’t be distinguishable.
This proposed graph extension is not a small change and caused a general logic overthinking. The basic approach is to define a new set of points and calculate a new Voronoi graph, containing more points along the coastline. I cannot just increase the points amount as it significantly slows the map generation and make it slow on zooming and dragging. So new elements addition should be accompanied by an unnecessary points removal.
I cannot insert additional points along the coastline not knowing where it lies, so a heightmap generation remains as is. When basic heightmap is done, I select a “coastal” polygons, i.e. polygons lying along the both sides of the coastline, and add these polygons’ points to a new array. To extend the coastline for each of them I add one more point for an every neighboring polygon of the same type (ocean or land). As a new point I take a 1/3 of the connecting line with a small random swing. My basic diagram has about 8k polygons, about 500 of them are “coastal”. As coastal polygons usually have two neighbors of the same type, the graph is extended for an additional 1000 elements. Not too much and as we already started to change the diagram, we can go further.
Out of 8k polygons 20-30% are land polygons and other are ocean and lake ones. So most of the resources go to the ocean part, while I’m not even render it. Potentially this data could be used for a various things like ocean decoration and sea trade routes, but all these stuff could be done without the initial graph. As we already added some ocean polygons along the coastline and extended them, we can just omit all other non-land polygons and forgot about them. This provides a space to make land polygons much more detailed, for example we can try to create a plausible mountain ranges. I did not explore all the options here and just added all the remained land polygon sites to the array without changing.
The result is quite interesting. From the initial 8k we got about 3k elements. You may notice how the reworked diagram resembles the landmass now still being a proper Voronoi diagram:
As I said before I’m not going to use this graph for an ocean related stuff, so it is OK that near-border polygons are so big. The extended “coastal” ocean polygons provide a kind of clip for a landmass, so the landmass remains almost untouched, while a new coastline looks much more detailed.
Below is the coastline versions comparison. The first two images show initial graph, the rest two are for a reworked one. On the very first and the third images coastline is linear, on the second and the fourth line is interpolated. Curved ones look more natural and beautiful and while the initial curved coastline (2nd) doesn’t coincide with the graph structure distinctly, the reworked coastline is much more detailed and allows some interpolation.
As a conclusion I have to say that this extension approach looks promising. I may try to detail the graph even more in a future, but as of now I’m quite happy with the result (the 4th image above).
The next aspect I want to cover is a heightmap templates. The initial routine generates rather good volcanic islands, so I will consider it as a first template — High Island. As was described in one of my previous posts the heightmap generation is an iteration model based on a “blob” placement. Initial big blob represents island core mountain, about 10-15 small blobs (“hills”) add some variety to the big island or can be a separate smaller islands. The template idea is to take these two landforms, add additional ones and combine them in a way to create a recognizable pre-made template.
Mountain remains a base landform for all templates. If I don’t want a map to have a mountain in the center, I still use this form and just re-scale the land heights to be more flat. Hill is also a good form, I just added the negative variant to represent a land depression, called Pit. I have also added a variable to control hills dispersion as it affects whether a map will be a single island or a couple of islands. A linear and narrowed variant of Hill is Range, its negative variant is Trough.
Combining and re-scaling these forms I have made 5 templates:
- High Island: mountain, ~15 hills, a couple of troughs, pits and ranges. I’ve added new forms to the template to make it look more interesting. In a rare cases it generates a couple of islands, it’s OK as templates are not intended to be something very rigid.
- Low Island: almost the same template, but without ranges and re-scaled to 0.3 modifier. So, having the same coastline, it looks more flat.
- Continental Islands: mountain, 5 troughs. Designed to be a couple of big “continental” islands, but usually produces a one big rugged island. Not sure, but I may change it to something different in a future.
- Archipelago: mountain, ~15 hills, 2 troughs and 8 pits. This works better, usually produces some small islands that look integrally connected.
- Atoll: even a bigger mountain with some special code to simulate the atoll generation. Actually, it takes mountain’s coastal polygons and increases their height a bit, while other land polygons are replaced by a shallow lagoon. The resulted map looks like an atoll, but I’m not sure this template is usable as landmass is too small and there are no any interesting features like mountains.
On a random map generation any of these 5 templates could be selected and applied. On a manual map creation, user will have an option to apply a template or add any landforms separately. I will also consider the idea of a built-in template editor, but as of now templates creation is not super flexible (I had to add a custom code to make the Atoll template).
It’s all to today. As usual comments are highly welcomed and I hope you will suggest some new templates to add. The current version is not deployed, I have to switch from JSFiddle to a local machine, so I will share the code only when it is a least partially finished or somebody asks me directly. Meanwhile you may check the alpha on Blocks, I have updated it with some features useful for a real D&D usage.