Bézier Curve Test
Here's a screenshot from the test application for the work with cubic Bézier curves I've been doing lately. Click the image at right to view the full picture.
The entire curve is made up of 20 nodes, forming 20 segments. Each node has an anchor point (the black dot) and two handles (the red and green lines); the ends of the handles define the knots for the cubic Bézier curve. The handles are made parallel to each other so that the curve appears smooth throughout. The angle and length of the handles are determined by the starting position of the node relative to its immediate neighbors. The nodes can be clicked and dragged around the screen to change the curve in real time. At this time, the handles of the nodes can't be changed with the mouse, but that is planned for the future.
The black "hairs" sticking out all over show the curve's normal at that position, i.e. the hairs are perpendicular to the curve at that location. The hairs are spaced every 0.5% of the entire curve's length. The normal for any given point is approximated as being perpendicular to a line connecting two closely-neighboring points on the curve. The curve's length is approximated by sampling every 5% of each segment (i.e. every 0.25% of the curve) and 'connecting the dots';. These methods aren't exact, but they are more than adequate for the purposes of a computer game.
The panda character (not shown in the preview; click to see the full image if you haven't) can move along the curve, rotating so that he is always aligned with the normal at that point.
One limitation of the program in its current form is that the length of the curve is re-evaluated whenever one of the nodes is moved, but the panda's location is not adjusted to compensate. This has the effect of making the panda seem to slide as the node is moved. This will be corrected in future versions.
Lastly, the curve itself is drawn using the Surface#draw_polygon_s
("draw solid polygon") method of the Rubygame library, which utilizes the SDL_gfx library. Future versions might be written in OpenGL, but this will require solving the additional problem of correctly filling the inside of the curve.