Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

233
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda