javafx - 尝试用箭头键使形状连续向一个方向移动
问题描述
我正在尝试制作一个蛇游戏,并且我在使用 JavaFX 方面相当陌生。我遇到的问题是,当我使用 switch 语句根据箭头键更改方向时,矩形只会在按下键时移动。我想要的是矩形继续沿按下的方向移动,直到按下另一个键。我确定有一个简单的解决方法,对不起,我对编码和 javaFX 还是新手。
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Mess extends Application {
private Stage window;
private final int WIDTH = 500;
private final int HEIGHT = 500;
private Direction snakeDir = Direction.RIGHT;
private int snake_W = 20;
private int snake_H = 20;
private Rectangle snake = new Rectangle(snake_W, snake_H);
private boolean running;
private boolean snakeUp = false;
private boolean snakeRight = true;
private Timeline timeLine = new Timeline();
enum Direction {
LEFT,RIGHT,UP,DOWN,NONE;
}
private Parent createContent() {
Pane root = new Pane();
root.setPrefSize(WIDTH,HEIGHT);
snake.setTranslateX((WIDTH / 4) - (snake.getWidth() / 2));
snake.setTranslateY(HEIGHT / 6);
KeyFrame keyFrame = new KeyFrame(Duration.millis(16), e -> {
if(!running) {return;}
switch(snakeDir) {
case UP:
snake.setTranslateX(snake.getTranslateX());
snake.setTranslateY(snake.getTranslateY() - 4);
break;
case DOWN:
snake.setTranslateX(snake.getTranslateX());
snake.setTranslateY(snake.getTranslateY() + 4);
break;
case LEFT:
snake.setTranslateX(snake.getTranslateX() - 4);
snake.setTranslateY(snake.getTranslateY());
break;
case RIGHT:
snake.setTranslateX(snake.getTranslateX() + 4);
snake.setTranslateY(snake.getTranslateY());
break;
}
});
timeLine.getKeyFrames().add(keyFrame);
timeLine.setCycleCount(Animation.INDEFINITE);
root.getChildren().addAll(snake);
return root;
}
private void startGame() {
running = true;
timeLine.play();
}
private void stopGame() {
timeLine.stop();
running = false;
}
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
window = primaryStage;
Scene mainScene = new Scene(createContent(),WIDTH,HEIGHT);
mainScene.setOnKeyPressed(e -> {
switch(e.getCode()) {
case UP:
snakeDir = Direction.UP;
break;
case DOWN:
snakeDir = Direction.DOWN;
break;
case LEFT:
snakeDir = Direction.LEFT;
break;
case RIGHT:
snakeDir = Direction.RIGHT;
break;
}
});
mainScene.setOnKeyReleased(e -> {
switch(e.getCode()) {
case UP:
case DOWN:
case LEFT:
case RIGHT:
snakeDir = Direction.NONE;
break;
}
});
window.setTitle("Snake");
window.setScene(mainScene);
window.show();
startGame();
}
}
我希望矩形能够沿着箭头键的方向连续移动。实际结果是,当一个键被按下时,它会移动一次并停止。
解决方案
这是我整理的一些代码,可以帮助您入门。按下按钮启动Timeline
。按向左或向右箭头键移动圆圈。每Timeline
16 毫秒循环一次。这接近 60 FPS。对于这样的游戏,我会将其更改为大约 40 FPS。这是一个宝贵的资源。这是另一个。
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* @author guest_account
*/
public class JavaFXApplication1 extends Application {
String input = "";
@Override
public void start(Stage primaryStage) {
Circle circle = new Circle(700 / 2, 700 / 2, 15, Color.BLUE);
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(16), (ActionEvent event) -> {
if(input.equals(KeyCode.RIGHT.toString()))
{
circle.setCenterX(circle.getCenterX() + 10);
}
if(input.equals(KeyCode.LEFT.toString()))
{
circle.setCenterX(circle.getCenterX() - 10);
}
if(input.equals(KeyCode.UP.toString()))
{
circle.setCenterY(circle.getCenterY() - 10);
}
if(input.equals(KeyCode.DOWN.toString()))
{
circle.setCenterY(circle.getCenterY() + 10);
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
Button btn = new Button();
btn.setText("Play");
btn.setOnAction((ActionEvent event) -> {
timeline.play();
btn.setDisable(true);
});
Pane boardRoot = new Pane(circle);
VBox.setVgrow(boardRoot, Priority.ALWAYS);
VBox root = new VBox(boardRoot, btn);
Scene scene = new Scene(root, 700, 700);
scene.setOnKeyPressed(keyEvent ->{
input = keyEvent.getCode().toString();
});
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
2019 年 6 月 8 日评论后的代码更新
推荐阅读
- microsoft-graph-api - 在 Microsoft Graph 客户端 API 中使用 ChunkedUploadProvider 进行附件时,“当前资源的受众声明值无效”
- excel - 尝试将文本框添加到 Excel 图表时未处理 NullReferenceException
- ios - xcode 中的奇怪错误(不能使用静态成员中心...)
- flutter - 如何在颤动时使 buttonBar 上的填充/空间更小?
- google-analytics - 如何跟踪另一个团队可能破坏分析规则条件的 HTML 更改?
- java - Apache Avro 和 Spring Data?
- java - 我该怎么做 AsyncLayoutInflater onCreate
- objective-c - Xcode Objective-C:下载自定义字体并将其显示在 UILabel 中
- encryption - 使用 helm 和 gcp_kms 加密 secrets.yml 文件时,密钥被拒绝
- laravel - 在代理后面运行 Laravel 本地服务器