2. Animating along a parametric curve
****
Let's say we use cubic bezier curves to specify the path. A curve is defined by four points P0, P1, P2, P3. P1 and P2 are control points. P0 and P3 could be cpatured touch points.
A point on the curve is defined by a formula B(t)= something (have a look at wikipedia or bezierat-function in cocos2d).
t is in the range from 0 to 1. To caclulate points on the curve you just need to solve the cubic bezier equation at a given t, eg. t=0.1, t=0.2, t=0.3 ... t=1.
This is one curve segment. If you have multiple curves they form a bezier spline. Every curve segment (every bezier curve) is defined by the four controlpoints where the last point of segment i-1 is the first point of the segment i.
The calculations to move the object on the curve segment are basically the same as for the polyline.
BUT the curve is round and the points calculated by solving with t=... are not equally distributed on the curve. What you need to know is the arclength of the curve, because it is not a straight line. Then you split the curve into equal sized segments and move your object using the calculations in (1).
Calculating the arclength can be done mathematically correct, but this needs a lot of cpu. As it's for a game ... we approximate it.
Let's say we split every curve into NUM_STEPS points. We choose 100 for NUM_STEPS here, this is enough for iPhone/iPad - I prefer ccpDistance(lastPoint, firstPoint) * 4 for NUM_STEPS.
Now we calculate the arclength of the curve:
int NUM_STEPS;
float dt = 1.f/NUM_STEPS;
float arcLength[NUM_STEPS];
float totalLength = 0;
CGPoint lastPoint, currentPoint;
for (float t=0, int i=0; t<=1.f; t+=dt, i++) {
currentPoint = bezierat(t, P0, P1, ...);
if (t > 0) {
float l = ccpLength(currentPoint, lastPoint)
arcLength[i] = arcLength[i-1] + l;
totalLength += l;
} else {
arcLength[0] = 0;
}
}
Now we can split the curve into equal sized segments, let's say segment size (length from one point to the next) should be SIZE. And we have the arcLength array from above. Just search in the arcLength array for the element where arcLength[i] == SIZE. As it is an approximation you will most times not find an element where it's really equal, so you have two elements where SIZE is inbetween. And that means the t we need is inbetween the t for these elements. I then just choose the middle of them.
So you have the t and can calculate the points on the curve segments in equal distance (or at least almost equal :).
But I said we have multiple curve segments -> a spline: C_i are the curve segments, where i=0..N.
With this you start with SIZE at the first curve segment. If it is shorter than SIZE substract the total arclength of this segment from size and search on the next curve segment with this new size.
If you find a point (t) on the curve segment, set SIZE to the initial value and start searching for a new t from the last found t. If the rest of the curve (from the last found t) is shorter than SIZE, substract the restlength from SIZE and go to the next curve segment.
After that the spline is split into equal distance segements and you can start moving your object as described in (1).
Choose SIZE according to your sprite size to get a smooth movement (I mean smooth curve segments).
(To fade out line segments just decrease the alpha values of your line vertices over time).