我在写一个地牢风格的游戏,地牢基本上是一个网格窗格。我想让玩家每0.5秒移动一格,如果他保持控制键。但我不知道如何做到这一点。我读过JavaFX:如何检测钥匙是否被按下。但这个问题与我的问题并没有特别的关系(除了我可以追踪发生了多少关键事件,或许可以在此基础上做更多)。所以我跟随这篇文章并尝试使用线程。sleep()解决了我的问题,但事实证明玩家只是停了几秒钟,然后突然移动了几格。
有人知道怎么解决吗?
@FXML
public void handleKeyPress(KeyEvent event) {
switch (event.getCode()) {
case UP:
System.out.println("Up");
player.moveUp();
break;
case DOWN:
System.out.println("Down");
player.moveDown();
break;
case LEFT:
System.out.println("Left");
player.moveLeft();
break;
case RIGHT:
System.out.println("Right");
player.moveRight();
break;
default:
break;
}
}
基本上,你必须记录你最后一次允许移动的时间,并且只有在经过指定的时间后才能再次移动。以下是概念证明:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Main extends Application {
private static final long THRESHOLD = 500_000_000L; // 500 ms
private long lastMoveNanos;
private Rectangle rect;
@Override
public void start(Stage primaryStage) {
rect = new Rectangle(25, 25, Color.DODGERBLUE);
rect.setStroke(Color.BLACK);
rect.setStrokeWidth(1);
var root = new Group(rect);
root.setOnKeyPressed(this::handleKeyPressed);
var scene = new Scene(root, 600, 400);
rect.setX(scene.getWidth() / 2 - rect.getWidth() / 2);
rect.setY(scene.getHeight() / 2 - rect.getHeight() / 2);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
root.requestFocus();
}
private void handleKeyPressed(KeyEvent event) {
if (event.getCode().isArrowKey()) {
event.consume();
long now = System.nanoTime();
if (lastMoveNanos <= 0L || now - lastMoveNanos >= THRESHOLD) {
switch (event.getCode()) {
case UP:
rect.setY(rect.getY() - rect.getHeight());
break;
case DOWN:
rect.setY(rect.getY() + rect.getHeight());
break;
case LEFT:
rect.setX(rect.getX() - rect.getWidth());
break;
case RIGHT:
rect.setX(rect.getX() + rect.getWidth());
break;
default:
throw new AssertionError();
}
lastMoveNanos = now;
}
}
}
}
上面以每500毫秒移动1次的最大速度移动矩形
,移动量等于其宽度/高度(以模拟“网格”)。如果位置变化应该是连续的,则可以使用动画进行移动(例如,设置了byX
和byY
属性的translation
)。使用动画时,如果持续时间与所需的调节时间一样长,则可以使用动画本身来跟踪下一步的允许时间。
更可靠的示例可能使用AnimationTimer
,并跟踪所有已按下但尚未释放的移动键(例如,在释放“当前”键时拾取最后一个仍按下的键,如果有)。下面是另一个概念证明:
import java.util.ArrayDeque;
import java.util.Deque;
import javafx.animation.AnimationTimer;
import javafx.scene.input.KeyCode;
import javafx.scene.shape.Rectangle;
class MoveAnimationTimer extends AnimationTimer {
private static final long THRESHOLD = 500_000_000L; // 500 ms
private final Rectangle node;
private final Deque<KeyCode> keyStack = new ArrayDeque<>(4);
private long then;
MoveAnimationTimer(Rectangle node) {
this.node = node;
}
void pushKeyIfAbsent(KeyCode code) {
if (code.isArrowKey() && !keyStack.contains(code)) {
keyStack.push(code);
start();
}
}
void removeKey(KeyCode code) {
if (code.isArrowKey()) {
keyStack.remove(code);
if (keyStack.isEmpty()) {
stop();
}
}
}
@Override
public void handle(long now) {
if (then <= 0L || now - then >= THRESHOLD) {
switch (keyStack.getFirst()) {
case UP:
node.setY(node.getY() - node.getHeight());
break;
case DOWN:
node.setY(node.getY() + node.getHeight());
break;
case LEFT:
node.setX(node.getX() - node.getWidth());
break;
case RIGHT:
node.setX(node.getX() + node.getWidth());
break;
default:
throw new AssertionError();
}
then = now;
}
}
}
问题内容: 我想控制Javafx TextField中的输入,以便只允许数字输入,这样,如果超出了最大字符数,则不会对文本框进行任何更改。 编辑:根据评论中的建议,我使用了JavaFX项目负责人建议的方法。阻止输入字母非常有用。我只需要它也可以过滤特殊字符。我尝试将过滤器更改为(text.matchs(“ [0-9]”),但不允许输入退格键。 edit2:找出一个特殊字符和长度的过滤器。这是我的最
新用户:从一月份开始学习Java,现在我正在使用NetBeans,如果我写这个简单的快捷方式,我会得到大量的错误。 所以IDE只是告诉我,我几乎做错了一切。在setOnKeyPressed的线路上,我得到了 我导入了所有内容,并从StackOverflow.com上的另一个问题(可能是有效的)中复制了这段代码。我只想按“esc”,并在root被聚焦的情况下关闭我的primarystage(不管是不
我正在开发一个javafx扫雷游戏,目前只使用鼠标左键输入。我想用鼠标右键也让用户可以标记可能的炸弹。我查看了Button类的Oracle网页,它说: “当按下并释放按钮时,将发送ActionEvent。应用程序可以通过实现EventHandler来处理ActionEvent来执行基于此事件的某些操作。按钮也可以通过实现EventHandler来处理MouseEvent来响应鼠标事件。” http
我想控制Javafx TextField中的输入,以便只允许数字输入,并且如果超过了最大字符数,则不会对TextBox进行任何更改。 编辑:根据注释中的建议,我使用了JavaFX项目负责人建议的方法。阻止信件被输入很有效。我只需要它也过滤特殊字符。我尝试将筛选器更改为(text.matchs([0-9]“),但这不允许输入退格符。
问题内容: 我有UISearchDisplayController的UISearchBar部分,该部分用于显示来自本地CoreData和远程API的搜索结果。我要实现的是在远程API上进行搜索的“延迟”。当前,对于用户键入的每个字符,都会发送一个请求。但是,如果用户输入速度特别快,那么发送许多请求就没有意义:这将有助于等待用户停止输入。有办法实现吗? 阅读文档建议您等到用户明确点击搜索后,但就我而