我做了一个蛇游戏(通过尝试遵循youtuber的代码),方向由WASD控制。然而,当我按下其中一个键时,什么都没有发生。如果我按住它,它会改变方向,但会有很大的延迟,可能会超过一秒钟。如何修复此问题?我已经查看了我的代码,并将其与我关注过几次的youtube代码进行了比较,但似乎仍然看不出问题出在哪里。这是我第一次做游戏,所以我对这个很陌生。
如果有帮助的话,这是我试图跟踪的视频。
https://www.youtube.com/watch?v=nK6l1uVlunc
package app;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.shape.Rectangle;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage; // Kontrollerer tittel, ikon, synlighet, størrelse, og dekorasjoner
import javafx.util.Duration;
public class App extends Application {
public enum Direction {
UP, DOWN, RIGHT, LEFT;
}
public static final int BLOCK_SIZE = 40;
public static final int APP_W = 20 * BLOCK_SIZE;
public static final int APP_H = 15 * BLOCK_SIZE;
public int score = 0;
public int highScore = 0;
private Direction direction = Direction.RIGHT; // Default spawn-bevegelse: til høyre
private boolean moved = false;
private boolean running = false; // Applikasjonen kjører
private Timeline timeline = new Timeline();
private ObservableList<Node> snake;
private Parent createContent() {
Pane root = new Pane();
root.setPrefSize(APP_W, APP_H);
Group snakeBody = new Group();
snake = snakeBody.getChildren();
Rectangle food = new Rectangle(BLOCK_SIZE, BLOCK_SIZE);
food.setFill(Color.RED);
food.setTranslateX((int)(Math.random() * (APP_W - BLOCK_SIZE)) / BLOCK_SIZE * BLOCK_SIZE);
food.setTranslateY((int)(Math.random() * (APP_H - BLOCK_SIZE)) / BLOCK_SIZE * BLOCK_SIZE);
KeyFrame frame = new KeyFrame(Duration.seconds(0.5), event -> {
if (!running)
return;
boolean toRemove = snake.size() > 1;
Node tail = toRemove ? snake.remove(snake.size()-1) : snake.get(0);
double tailX = tail.getTranslateX();
double tailY = tail.getTranslateY();
switch (direction) {
case UP:
tail.setTranslateX(snake.get(0).getTranslateX());
tail.setTranslateY(snake.get(0).getTranslateY() - BLOCK_SIZE);
break;
case DOWN:
tail.setTranslateX(snake.get(0).getTranslateX());
tail.setTranslateY(snake.get(0).getTranslateY() + BLOCK_SIZE);
break;
case RIGHT:
tail.setTranslateX(snake.get(0).getTranslateX() + BLOCK_SIZE);
tail.setTranslateY(snake.get(0).getTranslateY());
break;
case LEFT:
tail.setTranslateX(snake.get(0).getTranslateX() - BLOCK_SIZE);
tail.setTranslateY(snake.get(0).getTranslateY());
break;
}
moved = true;
if (toRemove)
snake.add(0, tail);
// Kollisjonsdeteksjon
// Krasjer i seg selv
for (Node rect : snake) {
if (rect != tail && tail.getTranslateX() == rect.getTranslateX() && tail.getTranslateY() == rect.getTranslateY()) {
restartGame();
break;
}
}
// Krasjer i kant
if (tail.getTranslateX() < 0 || tail.getTranslateX() >= APP_W || tail.getTranslateY() < 0 || tail.getTranslateY() >= APP_H) {
restartGame();
}
// Legg til mat
if (tail.getTranslateX() == food.getTranslateX() && tail.getTranslateY() == food.getTranslateY()) {
food.setTranslateX((int)(Math.random() * (APP_W - BLOCK_SIZE)) / BLOCK_SIZE * BLOCK_SIZE);
food.setTranslateY((int)(Math.random() * (APP_H - BLOCK_SIZE)) / BLOCK_SIZE * BLOCK_SIZE);
Rectangle rect = new Rectangle(BLOCK_SIZE, BLOCK_SIZE);
rect.setTranslateX(tailX);
rect.setTranslateY(tailY);
snake.add(rect);
}
});
timeline.getKeyFrames().add(frame);
timeline.setCycleCount(Timeline.INDEFINITE);
root.getChildren().addAll(food, snakeBody);
return root;
}
private void restartGame() {
stopGame();
startGame();
}
private void stopGame() {
running = false;
timeline.stop();
snake.clear();
}
private void startGame() {
direction = Direction.RIGHT;
Rectangle head = new Rectangle(BLOCK_SIZE, BLOCK_SIZE);
snake.add(head);
timeline.play();
running = true;
}
@Override
public void start(final Stage primaryStage) throws Exception {
// primaryStage.setTitle("My Application");
// primaryStage.setScene(new Scene(FXMLLoader.load(App.class.getResource("App.fxml"))));
// primaryStage.show();
Scene scene = new Scene(createContent());
scene.setOnKeyPressed(event -> {
if (!moved)
switch (event.getCode()) {
case W:
if (direction != Direction.DOWN)
direction = Direction.UP;
break;
case S:
if (direction != Direction.UP)
direction = Direction.DOWN;
break;
case A:
if (direction != Direction.RIGHT)
direction = Direction.LEFT;
break;
case D:
if (direction != Direction.LEFT)
direction = Direction.RIGHT;
break;
default:
break;
}
moved = false;
});
primaryStage.setTitle("Snake");
primaryStage.setScene(scene);
primaryStage.show();
startGame();
}
public static void main(final String[] args) {
App.launch(args); // Kaller init(), start() og så stop()
}
}
问题是每次触发关键帧时,都会重置移动标志。这需要用户在帧之间触发至少2个按键事件,以获得更改方向。
假设要防止用户在第一帧之前更改方向,则应删除if条件中的否定。(根据您试图使用标志实现的目标,您可能需要不同的修复)。
scene.setOnKeyPressed(event -> {
if (moved) {
switch (event.getCode()) {
case W:
if (direction != Direction.DOWN)
direction = Direction.UP;
break;
case S:
if (direction != Direction.UP)
direction = Direction.DOWN;
break;
case A:
if (direction != Direction.RIGHT)
direction = Direction.LEFT;
break;
case D:
if (direction != Direction.LEFT)
direction = Direction.RIGHT;
break;
default:
break;
}
}
});
此外,您还可以通过使用映射并向枚举添加属性来改进代码。
public enum Direction {
UP(0, -1), RIGHT(1, 0), DOWN(0, 1), LEFT(-1, 0);
private final int dx;
private final int dy;
private Direction(int dx, int dy) {
this.dx = dx;
this.dy = dy;
}
/**
* Tests, if 2 directions are parallel (i.e. both either on the x or the y axis).<br>
* Note: Depends on the order of the enum constants
* @param other the direction to compare with
* @return true, if the directions are parallel, false otherwise
*/
public boolean isParallel(Direction other) {
return ((ordinal() - other.ordinal()) & 1) == 0;
}
}
在关键帧中
...
double tailX = tail.getTranslateX();
double tailY = tail.getTranslateY();
Node head = snake.get(0);
tail.setTranslateX(head.getTranslateX() + BLOCK_SIZE * direction.dx);
tail.setTranslateY(head.getTranslateY() + BLOCK_SIZE * direction.dy);
moved = true;
...
final Map<KeyCode, Direction> keyMapping = new EnumMap<>(KeyCode.class);
keyMapping.put(KeyCode.W, Direction.UP);
keyMapping.put(KeyCode.S, Direction.DOWN);
keyMapping.put(KeyCode.A, Direction.LEFT);
keyMapping.put(KeyCode.D, Direction.RIGHT);
Scene scene = new Scene(createContent());
scene.setOnKeyPressed(event -> {
if (moved) {
Direction newDirection = keyMapping.get(event.getCode());
if (newDirection != null && !direction.isParallel(newDirection)) {
direction = newDirection;
}
}
});
我发现了您的代码与教程中的代码之间的差异。
if (!moved)
return;
switch (event.getCode()) {
.
.
.
}
moved = false;
在代码中,缺少if(!moved)后的return语句。我尝试将其添加到代码中,之后它对我有效。
希望这能解决你的问题干杯麦蒂
所以我正在制作一个游戏,记录你看到屏幕上弹出的东西后的反应时间,但我在获取反应时间方面有困难。我希望用户看到一个蓝色的球后按向上箭头键,我希望记录他们按下该按钮后的反应时间。 这是我的代码: 我用System.currentTimeMillis设置了一个“开始时间”来获取球变蓝后的时间,但我不确定这是否是正确的方法。 我还在“UpAction”类中设置了一个“stopTime”,我想在用户按下向上
2.17 响应时间(边缘) 2.17.1 描述 返回5分钟颗粒度的状态码明细数据,主要返回时间戳、省份、运营商、HIT/MISS、状态码、响应时间、请求数 2.17.2 请求地址 地址: https://api.bokecs.com/channel/responseTime?time={time}domain={domain} 2.17.3 请求方式 GET 2.17.4 请求参数 参数名称 是否
2.18 首包响应时间(边缘) 2.18.1 描述 返回5分钟颗粒度的状态码明细数据,主要返回时间戳、省份、运营商、HIT/MISS、状态码、响应时间、请求数 2.18.2 请求地址 地址: https://api.bokecs.com/channel/responseTime?time={time}domain={domain} 2.18.3 请求方式 GET 2.18.4 请求参数 参数名称
键盘移动 只需再做一点微小的工作,你就可以建立一个通过鼠标控制精灵移动的简单系统。为了简化你的代码,我建议你用一个名为keyboard的自定义函数来监听和捕捉键盘事件。 function keyboard(keyCode) { let key = {}; key.code = keyCode; key.isDown = false; key.isUp = true; key.p
我使用CXF和JAX-RS构建RESTFul API,为我的web应用程序提供数据。我想知道是否有可能记录请求X到达我的API、被处理然后作为响应返回所花费的时间。 我已经将自己的CXF记录器定义为JAX-RS特性,因为<code> 有没有一种方法可以从客户端跟踪时间并记录下来?
我正在通过一次发送250个请求来进行API负载测试。 1.配置 很自然,当很多用户同时请求时,服务器需要更长的时间来响应,这是它在这里说的。参见http://jmeter-plugins.org/wiki/responsetimesvsthreads/。然而,当测试这是我发现的… 活动线程与用户请求的数量相同吗?如果是,为什么会在一致的基础上发生? Update-1运行了另一个测试,并增加了这一次