
在javafx游戏开发中,animationtimer 是一个核心组件,用于驱动游戏循环,其 handle() 方法通常每秒被调用多次(例如,在60帧/秒的情况下,每秒60次)。当开发者尝试在 animationtimer 的 handle() 方法中,通过调用一个类似 handleinput() 的方法来处理用户输入时,常常会遇到一些非预期的行为。
原始代码中 Game 类的 handleInput() 方法存在以下关键问题:
这些问题共同导致了按键事件无法被正确捕获和跟踪,例如按下的键码不会被打印到控制台,甚至可能导致游戏退出等功能无法正常工作。
为了正确地处理JavaFX游戏中的键盘输入,核心思想是将事件监听器的注册与按键状态的维护分离开来,并确保它们在正确的生命周期内被管理。
以下是修正后的 Game 类,它演示了如何正确地处理键盘输入:
立即学习“Java免费学习笔记(深入)”;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.event.EventHandler;
import javafx.animation.AnimationTimer;
import java.util.ArrayList;
import java.util.List;
// Main class (保持不变,但为了完整性在此处包含)
public class Main extends Application {
private static Game game;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
game = new Game(stage);
final long startNanoTime = System.nanoTime();
new AnimationTimer() {
public void handle(long currentNanoTime) {
double t = (currentNanoTime - startNanoTime) / 1000000000.0;
game.update(t);
game.render();
}
}.start();
}
}
// 修正后的 Game 类
class Game {
private Stage stage;
private Group root;
private Scene scene;
private Canvas canvas;
private GraphicsContext gc;
final static int WINDOW_WIDTH = 800;
final static int WINDOW_HEIGHT = 600;
// 使用实例变量来存储当前按下的键
private List<KeyCode> input = new ArrayList<>();
public Game(Stage stage) {
this.stage = stage;
this.root = new Group();
this.scene = new Scene(this.root);
this.canvas = new Canvas(WINDOW_WIDTH, WINDOW_HEIGHT);
this.gc = this.canvas.getGraphicsContext2D();
this.stage.setTitle("Pong");
this.stage.setScene(this.scene);
this.root.getChildren().add(this.canvas);
// 在构造函数中只注册一次事件处理器
this.scene.setOnKeyPressed(
new EventHandler<KeyEvent>() {
public void handle(KeyEvent e) {
KeyCode code = e.getCode();
if (!input.contains(code)) {
input.add(code);
}
}
});
this.scene.setOnKeyReleased(
new EventHandler<KeyEvent>() {
public void handle(KeyEvent e) {
KeyCode code = e.getCode();
input.remove(code);
}
});
}
public void update(double time) {
// handleInput现在只负责读取和处理input列表
this.handleInput();
// 游戏逻辑更新,例如根据input列表移动角色
this.gc.setFill(Color.RED);
this.gc.fillRect(0,0, WINDOW_WIDTH, WINDOW_HEIGHT);
}
public void render() {
this.stage.show();
}
private void handleInput() {
// 打印当前按下的键,用于调试
System.out.println("当前按下的键: " + input);
// 在实际游戏中,会根据input列表中的键来更新游戏状态
// 例如:if (input.contains(KeyCode.LEFT)) { /* 角色向左移动 */ }
}
}正确处理JavaFX游戏循环中的键盘输入,关键在于理解事件驱动编程模型和变量作用域。通过将键盘事件监听器的注册与按键状态的存储分离,并确保它们在正确的生命周期内被管理,即:在初始化阶段一次性注册监听器,并使用实例变量来维护按键状态,可以实现稳定、高效且响应灵敏的用户输入处理。这不仅解决了按键无法被正确识别的问题,也为构建更健壮、更专业的JavaFX游戏奠定了基础。
以上就是JavaFX 游戏循环中键盘输入事件的正确处理方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号