Introduction
Paths can be defined to be bi-dimensional or tri-dimensional, because it is a template that takes a derived of the Vector class, thus you can either use it with a set of Vector2’s or Vector3’s.
Mathematically, it is defined as F(t) where t is [0, 1], where 0 is the start of the path, and 1 is the end of the path.
Types
As of v0.9.9, we have 3 implementations of the Path interface (the splines), these are:
Use
Splines can be used statically like this:
Vector2 out = new Vector2();
myCatmull.valueAt(out, t);
myCatmull.derivativeAt(out, t);
It is preferred that you do the second way, since it’s the only way guaranteed by the Path interface.
Snippets
This is often done at loading time, where you load the data set, calculates the spline and stores the points calculated. So you only evaluates the spline once. Trading memory for CPU time. (You usually should always cache if drawing static things)
/*members*/
int k = 100; //increase k for more fidelity to the spline
Vector2[] points = new Vector2[k];
/*init()*/
for(int i = 0; i < k; ++i)
{
points[i] = new Vector2();
myCatmull.valueAt(points[i], ((float)i)/((float)k-1));
}
Rendering cached spline
How to render the spline previously cached
Do everything at render stage
/*members*/
int k = 100; //increase k for more fidelity to the spline
CatmullRomSpline<Vector2> myCatmull = new CatmullRomSpline<Vector2>(dataSet, true);
ShapeRenderer shapeRenderer;
/*render()*/
shapeRenderer.begin(ShapeType.Line);
for(int i = 0; i < k-1; ++i)
{
shapeRenderer.line(myCatmull.valueAt(points[i], ((float)i)/((float)k-1)), myCatmull.valueAt(points[i+1], ((float)(i+1))/((float)k-1)));
}
shapeRenderer.end();
Make sprite traverse through the cached path
/*members*/
float speed = 0.15f;
float current = 0;
int k = 100; //increase k for more fidelity to the spline
/*render()*/
current += Gdx.graphics.getDeltaTime() * speed;
current -= 1;
float place = current * k;
Vector2 first = points[(int)place];
Vector2 second;
if(((int)place+1) < k)
{
second = points[(int)place+1];
}
else
{
second = points[0]; //or finish, in case it does not loop.
}
float t = place - ((int)place); //the decimal part of place
batch.draw(sprite, first.x + (second.x - first.x) * t, first.y + (second.y - first.y) * t);
Calculate sprite position on the path every frame, so it looks much more pleasant (you usually should always calculate on the fly if drawing dynamic things)
Make sprite look at the direction of the spline
The angle can be found when applying the atan2 function to the normalised tangent(derivative) of the curve.
myCatmull.derivativeAt(out, current);
float angle = out.angle();
As the arc-length of the spline through the dataSet points is not constant, when going from 0 to 1 you may notice that the sprite sometimes goes faster or slower, depending on some factors. To cancel this, we will change the rate of change of the time variable. We can easily do this by dividing the speed by the length of the rate of change. Instead of
change to: