java - JavaFX AnimationTimer 没有正确停止
问题描述
因此,我正在使用 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;
}
推荐阅读
- python - 类型对象'datetime.timezone'没有属性'now'
- ruby-on-rails - Rails 助手在 self 方法中将负号作为参数传递
- keycloak - Keycloak 重定向页面显示我们很抱歉.. 找不到页面
- common-lisp - 参数字符串是否可以不用双引号括起来?
- python - 需要帮助使用没有 API 的 Python 从 UPS 网站上抓取跟踪号详细信息
- android - 如何通过 REST API 将 APK/Bundle 上传到 Firebase 测试实验室?
- terraform - 如何为不是为 terraform 中的每个模块创建资源?
- c# - 如何使控件失去焦点单击它之外的任何位置?
- sql - SQLite 在递归 CTE 上是否存在性能不足或者我写错了 sql?
- swift - 使用 ToolbarItem(placement: .principal) re: largeTitle 的正确方法是什么?