Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating random tunnels

What methods could we use to generate a random tunnel, similar to the one in this classic helicopter game? Other than that it should be smooth and allow you to navigate through it, while looking as natural as possible (not too symmetric but not overly distorted either), it should also:

  1. Most importantly - be infinite and allow me to control its thickness in time - make it narrower or wider as I see fit, when I see fit;
  2. Ideally, it should be possible to efficiently generate it with smooth curves, not rectangles as in the above game;
  3. I should be able to know in advance what its bounds are, so I can detect collisions and generate powerups inside the tunnel;
  4. Any other properties that let you have more control over it or offer optimization possibilities are welcome.

Note: I'm not asking for which is best or what that game uses, which could spark extended discussion and would be subjective, I'm just asking for some methods that others know about or have used before or even think they might work. That is all, I can take it from there.

Also asked on gamedev. I think it fits in both places, since it's as much an algorithm question as it is a gamedev question, IMO.

like image 630
IVlad Avatar asked Sep 28 '12 20:09

IVlad


2 Answers

I think you could use Bézier curves for the tunnel walls, because they have the property that each end of the curve is tangent to the line segment between the last two control points at that end. This means it's possible to generate curves lazily, appending them as you go, without creating sharp corners. You only ever need to buffer one off-screen segment. As soon as its leftmost edge appears on-screen, create the next off-screen segment.

If you use cubic Béziers, you need 4 control points. The 1st will necessarily be the same as the last control point of the previous segment; to preserve smoothness at the junction, the 2nd will need to be somewhere on the line containing the previous segment's last 2 control points; the 4th will be where you want this curve to end; and the 3rd can probably be chosen freely. (You may want to keep it horizontally between the 1st and 4th points, to avoid the possibility of the curve "doubling back".)

Béziers have 2 other properties that will simplify your implementation:

  • The curve is completely contained within the convex hull defined by the control points, so it's easy to ensure there's a gap between the top and the bottom curves.
  • You can split a Bézier at any point to produce 2 sub-Béziers. This is handy for rasterising/linearising.

EDIT: Replaced "bounding box" with "convex hull".

like image 179
j_random_hacker Avatar answered Sep 28 '22 08:09

j_random_hacker


Decide on the width of the tunnel (it will probably reduce with distance), and then put 2 control points at a random height, but make sure that the vertical offset from the previous pair or points is small enough for the helicopter to make a manoeuvre. Continue adding control points at equal distances:

     _  
_         _    _

     _         _
_         _    

Next you need to find intermediate points. I'd use monotone cubic interpolation, which guarantees that all intermediate points are always between the control points, never lower or higher. Here's a demo I made in JavaScript: http://explored.tk/experiments/monotone/

UPD: or you can generate one such curve, and then draw the tunnel boundaries symmetrically around it.

like image 40
Alexey Lebedev Avatar answered Sep 28 '22 06:09

Alexey Lebedev