Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

232
Views
JavaFX AnimationTimer not stopping properly

So, I am creating the snake game using JavaFX and I cannot seem to make the game pause properly, i.e. it pauses occasionally and other times, the game just ignores the pause. So, basically I have a Main class where I initialize all the GUI components, and it also acts as the controller for the javafx Application.

I have a Button named gameControl which starts/pauses the game, a variable Boolean pause which keeps track of the game states (new/paused/running), and the methods startGame, pauseGame.

The gameControl button's EventHandler is as follows:

gameControl.setOnClicked(event->{
    if(paused == null) startGame(); //new game
    else if(paused) continueGame(); //for paused game
    else pauseGame();               //for running game
});

The startGame function looks something like this:

void startGame(){
    paused = false;
    Snake snake = new Snake(); //the snake sprite
    //following gameLoop controls the animation of the snake
    gameLoop = new AnimationTimer(){
        @Override
        public void handle(long now){
            drawSnake(); //draws the snake on the game
            snake.move(); //move snake ahead

            //following code is for slowing down the gameLoop renders to make it easier to play
            Task<Void> sleeper = new Task<>(){
                @Override
                protected Void call() throws Exception {
                    gameLoop.stop();
                    Thread.sleep(30);
                    gameLoop.start();
                    return null;
                }
            };
            new Thread(sleeper).start();
            //force garbage collection or else throws a bunch of exceptions after a while of running.
            //not sure of the cause...
            System.gc();
        }
    };
    gameLoop.start();
}

AnimationTimer gameLoop are variables of the class to allow calling from other functions.

And the pauseGame function:

void pauseGame() {
    paused = true;
    gameLoop.stop();
}

So, as I have said before the game doesn't pause everytime I hit the gameControl button, and I suspect it is due to the Thread.sleep(30); line inside the Task of the gameLoop. That being said, I am still not fully sure and have no idea how to fix this. Any help would be appreciated.

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

What type is 'paused' ? You check it for null, but then treat it as a boolean.. I can't understand why it would be a big 'B' Boolean object wrapper instead of the primitive boolean type.

This:

        //following code is for slowing down the gameLoop renders to make it easier to play
        Task<Void> sleeper = new Task<>(){
            @Override
            protected Void call() throws Exception {
                gameLoop.stop();
                Thread.sleep(30);
                gameLoop.start();
                return null;
            }
        };

Is an absolutely horrible way to throttle the speed. Let your game loop run, check the time on each loop to see if enough time has elapsed that you should update things. Your animation timer will drive the game. You don't want to pause the main platform thread, you don't want to pause any worker threads that are handling tasks. If you are scheduling tasks have them scheduled to run at the intervals that you want - don't throttle the thread in the call() method.

What you really want is something like this:

//following gameLoop controls the animation of the snake
gameLoop = new AnimationTimer(){
    @Override
    public void handle(long now){
        if ((now - lastTime) > updateIterval) {
            drawSnake(); //draws the snake on the game
            snake.move(); //move snake ahead
            lastTime = now;
        }

You could even make that a loop to "catch up" in case the Animation timer fell behind for some reason:

        while ((now - lastTime) > updateIterval) {
            drawSnake(); //draws the snake on the game
            snake.move(); //move snake ahead
            lastTime += updateIterval;
        }
over 4 years ago · Santiago Trujillo Report

0

Your intuition that Thread.sleep(30); may be causing an issue is on the right track. A user may click the button calling pauseGame, setting paused to true, and telling the gameloop to stop. If the new sleeper thread is started and sleeping at that moment it will call start() on the gameloop when it wakes up.

One option may be to simply check the value of paused in the sleeper task to determine if it should start the gameloop.

Task<Void> sleeper = new Task<>(){
    @Override
    protected Void call() throws Exception {
        gameLoop.stop();
        Thread.sleep(30);
        if (!paused) {
            gameLoop.start();
        }
        return null;
    }
};

Given that the paused value is being set and read from multiple threads, I would recommend adding a mechanism to ensure you don't get non-deterministic behavior. Swapping the Boolean to an AtomicBoolean is a straight forward option for ensuring consistency.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!