How To Generate Procedural Racetracks Without Noise
bordeen.blogspot.com
bordeen.blogspot.com
Instead of generating a convex hull, use polar coordinates and generate points in a circle or ellipse with a random radius modifier (since these tracks don't have overlaps this method should work fine). You can pretty easily control the spacing and delta in the radius and theta, and then just use Bezier curves from there which should not have weird cusps that the author describes if your spacing is correct. With a few modifiers (like using Manhattan distance for the radial measurement) you can make some variations like more "square" tracks although this would introduce (potentially) new complications.
That said, the author's implementation works great regardless of complexity and would probably fair better with more complex track types.
[1] http://imgur.com/gallery/13k1R [2] https://github.com/Lockyy/YOGO-Moment-of-Interaction
Often in day-to-day work algorithms aren't immediately useful. But when they are, they really make a difference.
I'm surprised that there are not more "design your own track" racing games. It feels like that kind of user customisation is popular, and sharing tracks would be very popular.
It might be a good idea to look at the https://en.wikipedia.org/wiki/Euler_spiral to make the curves more "realistic" or convenient to drive through. If this would be desirable of course depends on the type of game.
That immediately defeats the "Without Noise" requirement.
I think it was worth pointing out in the context of this post, though, as he took the time to directly address the part of his audience who apparently seems to think all "procedural" content should descend from a noise function, which is probably common with beginners. Often a simple random number generator will do just fine.
You can trivially create a race track by following a route of a certain height in a perlin noise map. No algorithm needed at all. All you need is 2d perlin noise and a single if block:
for x, y in range():
if lower < perlin[x][y] < higher:
map[x][y] = brown
else:
map[x][y] = green
The author just decided to take a different approach.One approach would be to then walk the line from the start and connect neighboring points that aren't too close to previous points and don't cause a turn tighter than some given angle (non-simple curves should only happen if you're unlucky enough to run into a saddle point of your desired value), but that solution starts looking a whole lot like taking the convex hull of clusters of random points...you could have just taken fewer points and then smoothed the curve that fits around them :)