JavaFXAnimationTimer没有正确停止
所以,我正在使用 JavaFX 创建蛇游戏,我似乎无法让游戏正确暂停,即它偶尔会暂停,而其他时候,游戏只是忽略了暂停。所以,基本上我有一个Main
类,我在其中初始化所有 GUI 组件,它还充当 javafx 应用程序的控制器。
我有一个启动/暂停游戏的Button
命名gameControl
,一个Boolean pause
跟踪游戏状态(新/暂停/运行)的变量,以及方法startGame
, pauseGame
。
该gameControl
按钮的EventHandler
情况如下:
gameControl.setOnClicked(event->{
if(paused == null) startGame(); //new game
else if(paused) continueGame(); //for paused game
else pauseGame(); //for running game
});
该startGame
函数看起来像这样:
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
是允许从其他函数调用的类的变量。
和pauseGame
功能:
void pauseGame() {
paused = true;
gameLoop.stop();
}
因此,正如我以前说过的游戏不会暂停,每次我打的gameControl
按钮,我怀疑这是由于Thread.sleep(30);
内部线路Task
的gameLoop
。话虽如此,我仍然不完全确定,也不知道如何解决这个问题。任何帮助,将不胜感激。
回答
什么类型是“暂停”?你检查它是否为空,然后把它当作一个布尔值......我不明白为什么它会是一个大的 'B' 布尔对象包装器而不是原始布尔类型。
这个:
//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;
}
};
是一种绝对可怕的方式来限制速度。让您的游戏循环运行,检查每个循环的时间,看看是否已经过去了足够的时间来更新内容。您的动画计时器将推动游戏。您不想暂停主平台线程,也不想暂停任何正在处理任务的工作线程。如果您正在安排任务,请安排它们以您想要的时间间隔运行 - 不要在 call() 方法中限制线程。
你真正想要的是这样的:
//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;
}
您甚至可以将其设为循环以“赶上”,以防动画计时器因某种原因落后:
while ((now - lastTime) > updateIterval) {
drawSnake(); //draws the snake on the game
snake.move(); //move snake ahead
lastTime += updateIterval;
}