Using Perlin noise for creating terrain is a simple, powerful approach, that unfortunately does not offer a lot of control over the gameplay experience. One can say it simply is too random.
This was an exploration of mixing Perlin noise with a node-based approach to create a more directed gameplay experience.
This early example is one of the clearest examples of how the approach works. The terrain is broken up into a number of tiles. For instance, the peninsula on the right side is made up of a dirt-tile, a grass-tile, and then more dirt tiles at the bottom.
The world-tiles themselves are square, but when the smaller tiles are picked, their position is offset by Perlin-noise, so that the shape of the squares are heavily distorted. While the world-tiles are easy to tell apart over on the right side, by the desert, the generation method is more succesfully obscured.
While the world-tiles themselves allow some control - you can say that you want X amount of tiles of one terrain and Y amount of tiles of another - the real goal behind them is to afterwards use the centre of every tile as a node. These nodes can then be connected to form the paths that the player will traverse while exploring the island.
While the world-tiles themselves allow some control - you can say that you want X amount of tiles of one terrain and Y amount of tiles of another - the real goal behind them is to afterwards use the centre of every tile as a node. These nodes can then be connected to form the paths that the player will traverse while exploring the island.
The paths are generated by walking, tile by tile, from the centre of one node to another. Each step, there is a 25% chance to change direction towards the goal, displaced by up to 65 degrees. Each step, the ground underneath the current position is also checked. If there already is another path, the path is given up. If there is water, it either gives up or builds a bridge, depending on whether a bridge is needed.
After paths are laid, for all tiles, the distance to the nearest path is calculated. The further away, the higher chance to be marked black as seen above, and then later filled with obstacles. In the areas far away from the path but not quite black yet, obstacles are also placed, but not tightly enough to act as walls.
I took some inspiration by this post from u/Dicethrower to use the distance from the path AND Perlin noise to figure out if the tile should be blocked or not. Some places, only the direct path is clear, and straying away from it is impossible. Other places, the Perlin noise permits a wider clearing that the player can explore to find beaches, small sights, or perhaps an unintended route to a later node.
I took some inspiration by this post from u/Dicethrower to use the distance from the path AND Perlin noise to figure out if the tile should be blocked or not. Some places, only the direct path is clear, and straying away from it is impossible. Other places, the Perlin noise permits a wider clearing that the player can explore to find beaches, small sights, or perhaps an unintended route to a later node.
The game itself is based around a game concept I did, what, five or more years ago. On each island, there are four pieces of a portal and a portal nexus. You must find the four pieces and bring them back to the nexus, while fighting the Island's magical inhabitants.
The node based approach works quite easily with this concept. 15 nodes are generated, and at five of them, a point of interest is placed. In this case, it is necessary for the routing algorithm to connect all nodes with each-other. However, often enough the routes throw loops that makes them feel more like exploring an island than just wandering from spot to spot.
In the current iteration, the strength of Perlin noise has been tuned to let the world tiles be noticeable only to the knowable observer. Additionally, to let each location feel more unique, when picking an obstacle, it is also done on a tile-based approach so similar tiles stand next to each-other.
When generated, a number of world-tiles are picked to be water instead of land. Later, the routing algorithm tries as hard as it can to connect all tiles without crossing water, but once a treshold is met, it starts building bridges. They happen rarely enough that they seem more a point of interest than a developer shortcut. It does happen that bridges are not necessary, but since the unpathed terrain is filleed with obstacles, this does not matter.
While early islands have mostly grassy and light forest as terrains, the later islands pick from more inhospitable terrains. That is the idea, at least - for now, the different terrains are only difference in the colour and texture of the ground, and the choice of obstacles.
In the above picture, you might also notice the prominent height differences. The height-map of the island is another layer of Perlin noise, that is independent of terrain and whether a tile is next to water. It is a simple solution to the problem with little downside, since the cliffs are made to break up the beach, that would otherwise become too ubiquitous.
Currently, cliffs are impossible to traverse, and since they are placed independently before paths are made, the paths simply, er, break the cliff? When you see a hole in the cliff, it is proof that a path has gone through there. I should probably add some graphical explanation, like a stair-case or incline or whatever fits. The forced 2/3s perspective makes it a bit difficult, though.
Evaluation
I am quite happy with the result of the islands themselves. I do not think I have quite hit the balance between natural Perlin noise and guided nodes and paths, but it is better than what I had before. However, I am finding that designing gameplay around enemies relies just as much on random chance as before.
On top of that, right now, the generation takes place all in one go at the beginning of the game, which is a bit slow. Five, maybe ten seconds. This may be caused by using an 8x8 pixel tile as the base, meaning that even what would be a 1920x1080 pixels map would be 32400 tiles. It also makes my laptop chug along. After implementing a 3D-perspective, it only just runs at 30 fps.
The gameplay is simple. There are enemies and randomly generated wands (weapons) that you can use to fight them. The original game 5 years ago, whose sprites I still use, had a bigger focus on survival elements, collecting edible items and materials for campfires to last through the night. This worked better with the original, open islands with few obstacles. If you look at the above pictures, obstacles are abundant now. Thus, the generation approach trades tighter enemy gameplay (since you can't just run around enemies) with worse survival gameplay (since you can't just run around the island).
The terrains are adequately different, but hardly unique. I think their strength is in their difference to each-other, which borders on aesthetically pleasing, while looking at each terrain on its own is less interesting.