Currently, to move a fly from position to position, I'm using this :
DirectionNormalized = (positionTarget - position).Normalize;
and
position += DirectionNormalized *
vitesseP2P *
(float)gameTime.ElapsedGameTime.TotalMilliseconds;
So, the fly flies (joke : done) in a line from A point to B point to C point to D point etc.
But I would like to curve its trajectory. It's incredible, I thought it was easy but I'm stuck for hours.
hope you can help.
The most common way to achieve this is by using a Bezier curve. The Bezier algorithm takes a set of points - two end points and a number of control points - and produces a series of points at various positions along the curve defined by those points.
The generalized form of the Bezier algorithm is an iterative reduction, but we can unroll it for the specific 4-point case and generate a BezierInterpolate
function like this:
public static Vector2 BezierInterpolate(Vector2 p0, Vector2 p1, Vector2 c0, Vector2 c1, float fraction)
{
// first stage, linear interpolate point pairs: [p0, c0], [c0, c1], [c1, p1]
Vector2 p0c0 = Vector2.Lerp(p0, c0, fraction);
Vector2 c0c1 = Vector2.Lerp(c0, c1, fraction);
Vector2 c1p1 = Vector2.Lerp(c1, p1, fraction);
// second stage, reduce to two points
Vector2 l = Vector2.Lerp(p0c0, c0c1, fraction);
Vector2 r = Vector2.Lerp(c0c1, c1p1, fraction);
// final stage, reduce to result point and return
return Vector2.Lerp(l, r, fraction);
}
This will give you the position of a point that is a certain fraction along the curve. If you have a start and finish time of your animation for instance, you can generate the current position of your fly using the above.
First though, you need to define the control points. I'd use something like this:
static System.Random prng = new System.Random();
public static Vector2 genControlPoint(Vector2 l, Vector2 r)
{
// get a random angle between +/-(15..90) degrees off line
float angle = (float)((((prng.NextDouble() * 5) + 1) / 12) * Math.PI * (prng.Next(0, 2) * 2 - 1));
// create rotation matrix
Matrix rot = Matrix.CreateRotationZ(angle);
// get point offset half-way between two points
Vector2 ofs = Vector2.op_Multiply(Vector2.op_Subtract(l, r), 0.5);
// apply rotation
ofs = Vector2.Transform(ofs, rot);
// return point as control
return Vector2.op_Add(l, ofs);
}
....
Vector2 p0 = FlyStartPoint();
Vector2 p1 = FlyEndPoint();
// generate randomized control points for flight path
Vector2 c0 = genControlPoint(p0, p1);
Vector2 c1 = genControlPoint(p1, p0);
At this point you have a set of four points suitable for passing as the first 4 parameters to the BezierInterpolate method, from which you can determine the position of the 'fly' at a specific time.
Bezier curves start out scary, but once you understand them they are useful tools. Doing it by hand as I do here gives you a bit more understanding of what is actually going on in the background when you call Vector2.Hermite
or Vector2.CatmullRom
.