Why AnimationTimer and setTranslate on a ImageView node create jerky movement?

My goal is to create a basic 2D game using the Java Fx library. And my subgoal is to create responsive controls and smooth movement of the character. My issue is the player in my game (ImageView node) is a little jerky when I use setTranslate on it. It seems to jerk for every second of continuous movement. Included in this post is an example. I’ve done research and I’ve been given conflicting answers… For instance, one person told me to use a WritableImage(because he said it’s like BufferedImage), but that didn’t seem to solve the jerkyness issue(maybe I implemented it wrong). Any help would be most appreciated.

package pleasehelp;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;

import javafx.stage.Stage;

public class PleaseHelp extends Application {

    ImageView imageView;

    public void start(Stage stage) {

        Pane root = new Pane();

        Scene scene = new Scene(root, 800, 200);

        stage.setTitle("Please Help!");

        stage.setScene(scene);

        Animation animation = new Animation(this);

        Image image = new Image("http://lessonpix.com/drawings/192/100x100/Gray+Square.png");
        imageView = new ImageView();
        imageView.setImage(image);
        root.getChildren().add(imageView);
        animation.start();

        stage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }

}
package pleasehelp;

import javafx.animation.AnimationTimer;

public class Animation extends AnimationTimer {
    
    PleaseHelp please;
    
    Animation(PleaseHelp please) {
        this.please = please;
    }
    
    @Override
    public void handle(long now) {
        please.imageView.setTranslateX(please.imageView.getTranslateX() + 1);
    }
    
    public void start() {
        super.start();
    }
    
    public void stop() {
        super.stop();
    }
    
}

It might be a “fix the timestep” issue?

I didn’t use javafx, but having the ‘now’ parameter in the handle() callback method screams variable timestep to me.

You need to incorporate the now into your calculation. The javadoc says it is the timestamp of a frame in nanoseconds. You may need to save it at the first frame, so you are able to calculate the relative time to the start of the animation per frame…

Also this looks helpful: http://svanimpe.be/blog/game-loops-fx.html

Unfortunately the timestamp does not quite match up with monitor sync rate so it’ll always be a teeny bit juddery. JavaFX still has a ways to go for games.

Cas :slight_smile:

In my limited experience, AnimationTimer does a pretty good job of maintaining 60fps. When I ran the code, it looked fine. I’m not clear what the problem is.

If the scan rate on the monitor is something more different from 60, like 75 say, maybe that would help? I couldn’t test this because I can’t find where Windows10 let’s one set the monitor refresh rate.

You might find it interesting to store the highest and lowest deviations. Store the last “now” long and compare it to the current “now” argument from the handle method. Or to tally the range of timing differences that occur.

Here is a short JavaFX graphics test program I wrote that is similar to your code (object bouncing side to side), though I am not using an ImageView in this case. Use of ImageView shouldn’t make a difference. As far as I know this animation is reasonably smooth. Does it work for your setup?

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class BasicGraphicsDemo2 extends Application{

	final int WIDTH = 600;
	final int HEIGHT = 400;
	
	double ballRadius = 40;
	double ballX = 100;
	double ballY = 200;	
	double xSpeed = 4;
	
	public static void main(String[] args) {
		
		launch(args);
	}
	
	@Override
	public void start(Stage stage) throws Exception {
	
		stage.setTitle("Basic JavaFX demo");
		
		Group root = new Group();
		Scene scene = new Scene(root, WIDTH, HEIGHT);
		
		Circle circle = new Circle();
	
		circle.setCenterX(ballX);
		circle.setCenterY(ballY);
		circle.setRadius(ballRadius);
		circle.setFill(Color.BLUE);
		root.getChildren().add(circle);
		
		stage.setScene(scene);		
		stage.show();

		AnimationTimer animator = new AnimationTimer()
		{
			@Override
			public void handle(long arg0)
			{
				ballX += xSpeed;
				
				if (ballX + ballRadius >= WIDTH)
				{
					ballX = WIDTH - ballRadius;
					xSpeed *= -1;
				} else if (ballX - ballRadius < 0) {
					ballX = 0 + ballRadius;
					xSpeed *= -1;
				}
	
				circle.setCenterX(ballX);
			}	
		};

		animator.start();

	}
}

For responsive controls, what I recommend is to have asynchronous input (keyboard and mouse) be used to set volatile variables. Then, in the AnimationTimer (the game loop), consume those values and update the animations accordingly. This is working pretty well so far on the 2D game JavaFX game I work on intermittently.

Thank you for the responses. I found out what the issue was. I use a program called f.lux that automatically adjusts screen brightness based on the time of day and it was drastically affecting the game’s performance for some reason.

Thanks for letting us know the resolution.