Таймер анимации 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()
}