0
votes

For a game I am developing I want to animate an object along a path. There are three sides to this; therefore I am unsure what approach is the best solution.

The path animation

Currently the path is made up as a series of points which means I am using Path with only straight lines. However I intend to change this later on to a Bézier curve. Currently the points are at a distance between 5 and 8 pixels. I also intend to reduce the number of control points on the curve. When saying animation I am thinking PathTransition, but I am not set on this, as based on the various constraints there might be better solutions.

The object that is animated along the path is an ImageView but could also be something as simple as a Shape (like Circle).

The duration

The game is driven by a timer. The timer sends tick events. How much ingame time has passed for an tick depends on the tick interval: An ingame tick can represent the passing of 5 minutes or one hour. A tick happens every 100 ms.

Based on the tick interval it is possible to determine the initial duration of the animation:

int intervalInMinutes = 5;
int ingameAnimationDurationInMinutes = 60 * 24;
int nbTicks = ingameAnimationDurationInMinutes / 5; // = 288
int durationInMs = 100 * nbTicks; // 28800 ms = 28.8s

However it is possible that the tick interval changes at any time (e.g. 5 minutes -> 30 minutes). This means that the remaining animation should be sped up by factor 6. At this point I see the following options:

  • Update the duration of the animation. For a PathTransition this seems easy, but other approaches (like KeyFrame animation) might have an issue here.
  • Stop the running animation and reinitialize the animation from the current position. I think this could be difficult as the current location may not match with one of the control points in the curve, which would mean that the curve (or at least the first segment) needs to be recalculated.
  • Create the animation iteratively: animate along the curve only for one tick. For this approach the same issues apply as for the one above: When the animation is finished the position of the animated object must be at a control point. If the tick interval changes the segments between the control points change as well.

External update

The position of the animated object needs to be updated in it's model so other parts of the code can react to the changed position. I can envision various scenarios here:

  • On each tick query the position of the object that is animated and update the position in it's model
  • Animation updates the position of the object. For this approach however I would probably need an KeyFrame animation or even a KeyFrame animation together with an Interpolator.
  • Do not use one of the built in animations, but update the position on each tick (as there are only 10 ticks/s this will not result in a smooth animation)

What is a good approach to address these requirements without making the solution too complicated? It is well possible that there are aspects that I have overlooked or even other options that I am unaware of.

1
I think the built-in animations work best when you expect them to run to completion with a fixed rate in the vast majority of cases. In other cases, such as the one you describe, using a different solution usually seems to work better. Consider using an AnimationTimer to handle the "ticks": this will ensure animation as smooth as possible. Have a look at Steven van Impe's blog posts (part 1 and part 2. (2 is JavaFX).James_D
Also this question and answer is pretty useful, as it provides an interpolator method that updates the node and can be used in an AnimationTimer. If I return the new location from the interpolate method and handle the UI update in the AnimationTimer that should give me more freedom, as there will be many moving object, but only a few need to be rendered.hotzst

1 Answers

1
votes

If you switch right now to Bezier curves, I think your problem is instantly solved. Bezier curves have a parameter space, usually [0,1], which somewhat translates to speed (the argument of a curve is usually named t for time in mathematics for a reason). Therefore, if you have your curve, either as an actual polynom or as some control points that you evaluate by de Casteljau, all you need to know about your progression on the curve is the progression within the parameter space.

Therefore, a tick would be a certain distance within the parameter space, like 1/1000 if 1000 ticks is how many ticks it takes to finish the curve. You'd simply add 1/1000 to the current value of the parameter and evaluate your curve for that one.

If that's not smooth enough for you, then you could do the following: Think of as the next ticks position as where you want to be and do an animation to that from your current position in linear manner. If your ticks subdivide the curve fine enough, nobody will be able to see the linear segments (this should suffice for a game, wouldn't do it for a cutting machine).