Таймер анимации Scalafx, вызывающий рекурсию: можно ли этого избежать?

Я пытаюсь сделать игру, которая использует класс AnimationTimer, чтобы справиться с этим. Резюме моего кода выглядит примерно так:

Основной класс

object Game extends JFXApp{

    def showMenu{
        //code that show the .fxml layout and controller will handle the controller
    }

    def showInstruction{
        //code that show the .fxml instruction
    }

    def showGame():Unit = {
        this.roots.center = {
            new AnchorPane(){
                children = new Group(){

                    val timer:AnimationTimer = AnimationTimer(t=> {
                        //game code

                        if(playerDie){
                            timer.stop
                            val gameOver:AnimationTimer = AnimationTimer(t => {
                                if(exitPressed){
                                    showMenu
                                } else if (restartPressed){
                                    restartGame
                                }
                            })
                            gameOver.start
                        }
                    })
                    timer.start
                }
            }
        }
    }

    def restartGame(){
        //show restart layout
    }

    showMenu()
}

RestartController

@sfxml
class RestartController(private val countDownLabel:Label){
    var lastTimer:Double = 0
    var countDownSec:Double = 5.999
    val countDown:AnimationTimer = AnimationTimer(t => {
        val delta = (t-lastTimer)/1e9
        if(delta < 1) countDownSec -= delta
        countDownLabel.text = countDownSec.toInt.toString
        if(countDownSec <= 0) {
            countDown.stop
            Game.showGame
        }
        lastTimer = t
    })//end AnimationTimer pauseTimer
    countDown.start

    //I think Game.showGame should be located at here but tried several ways still can't implement it

}

У меня есть некоторая переменная, такая как уровень игры, которая находится в некотором классе в объекте-компаньоне, поэтому я хочу избежать рекурсии, потому что, если она станет рекурсивной, это приведет к противоречивым результатам для уровня.

Когда игрок мёртв, если пользователь выходит из игры, пользователю будет показано меню, и если игрок снова нажмет "начать игру", он не покажет несоответствия для этих переменных в объекте-компаньоне.

Однако, если игрок нажмет перезагрузку, он перейдет в рекурсивный режим, что означает, что метод вызывает другой метод, и, следовательно, старый метод не завершился и скажет, если я сделаю что-то подобное

ShootingGame.level += 1 //be trigger when certain requirement meet

Иногда это будет += 2 или даже больше

Есть ли какое-то решение, чтобы сделать его не рекурсивным, который ведет себя точно так же, как когда я выхожу из игры, и старый метод showGame() полностью завершится, прежде чем я начну новый??

2 ответа

Решение

Попробуйте не вызывать ту же функцию, вместо этого я заново инициализирую всю программу, как показано ниже:

Стрелялки

class ShootingGame{
    def restart:ListBuffer[Circle] = {
        var toBeRemove:ListBuffer[Circle]

        //initialize and add those needed to be remove into toBeRemove

        toBeRemove
    }
}

Основной класс

объект Game расширяет JFXApp{

    def showMenu{
        //code that show the .fxml layout and controller will handle the controller
    }

    def showInstruction{
        //code that show the .fxml instruction
    }

    def showGame():Unit = {
        this.roots.center = {
            new AnchorPane(){
                children = new Group(){

                    val timer:AnimationTimer = AnimationTimer(t=> {
                        //game code

                        if(playerDie){
                            timer.stop
                            val gameOver:AnimationTimer = AnimationTimer(t => {
                                if(exitPressed){
                                    showMenu
                                } else if (restartPressed){
                                    for(i <- game.restart) children.remove(i)
                                    timer.start
                                }
                            })
                            gameOver.start
                        }
                    })
                    timer.start
                }
            }
        }
    }

    showMenu()
}

Я решил проблему, не перезванивая ту же функцию, вместо этого я заново инициализировал всю программу, как показано ниже:

ShootingGame

class ShootingGame{
    def restart:ListBuffer[Circle] = {
        var toBeRemove:ListBuffer[Circle]

        //initialize and add those needed to be remove into toBeRemove

        toBeRemove
    }
}

Основной класс

object Game extends JFXApp{

    def showMenu{
        //code that show the .fxml layout and controller will handle the controller
    }

    def showInstruction{
        //code that show the .fxml instruction
    }

    def showGame():Unit = {
        this.roots.center = {
            new AnchorPane(){
                children = new Group(){

                    val timer:AnimationTimer = AnimationTimer(t=> {
                        //game code

                        if(playerDie){
                            timer.stop
                            val gameOver:AnimationTimer = AnimationTimer(t => {
                                if(exitPressed){
                                    showMenu
                                } else if (restartPressed){
                                    for(i <- game.restart) children.remove(i)
                                    timer.start
                                }
                            })
                            gameOver.start
                        }
                    })
                    timer.start
                }
            }
        }
    }

    showMenu()
}
Другие вопросы по тегам