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:

  1. Vector2 out = new Vector2();
  2. myCatmull.valueAt(out, t);
  3. 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)

  1. /*members*/
  2. int k = 100; //increase k for more fidelity to the spline
  3. Vector2[] points = new Vector2[k];
  4. /*init()*/
  5. for(int i = 0; i < k; ++i)
  6. {
  7. points[i] = new Vector2();
  8. myCatmull.valueAt(points[i], ((float)i)/((float)k-1));
  9. }

Rendering cached spline

How to render the spline previously cached

Do everything at render stage

  1. /*members*/
  2. int k = 100; //increase k for more fidelity to the spline
  3. CatmullRomSpline<Vector2> myCatmull = new CatmullRomSpline<Vector2>(dataSet, true);
  4. ShapeRenderer shapeRenderer;
  5. /*render()*/
  6. shapeRenderer.begin(ShapeType.Line);
  7. for(int i = 0; i < k-1; ++i)
  8. {
  9. shapeRenderer.line(myCatmull.valueAt(points[i], ((float)i)/((float)k-1)), myCatmull.valueAt(points[i+1], ((float)(i+1))/((float)k-1)));
  10. }
  11. shapeRenderer.end();

Make sprite traverse through the cached path

  1. /*members*/
  2. float speed = 0.15f;
  3. float current = 0;
  4. int k = 100; //increase k for more fidelity to the spline
  5. /*render()*/
  6. current += Gdx.graphics.getDeltaTime() * speed;
  7. current -= 1;
  8. float place = current * k;
  9. Vector2 first = points[(int)place];
  10. Vector2 second;
  11. if(((int)place+1) < k)
  12. {
  13. second = points[(int)place+1];
  14. }
  15. else
  16. {
  17. second = points[0]; //or finish, in case it does not loop.
  18. }
  19. float t = place - ((int)place); //the decimal part of place
  20. 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.

  1. myCatmull.derivativeAt(out, current);
  2. 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: