Trying to make the shape continuously move in one direction with arrow keys

痴心易碎 提交于 2019-12-02 14:23:17

问题


I am attempting to make a snake game an I am fairly new at using JavaFX. The problem I am running into is when I use a switch statement to change the direction based on the arrow keys they rectangle will only move when the key is pressed. What I want is the rectangle to keep moving in the direction pushed until another key is pressed. Im sure there's an easy fix, I'm sorry, I'm still new to coding and 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();
    }
}

I expect the rectangle to continuously move in the direction of the arrow key pushed. The actual result is when a key is pressed it moves once and stops.


回答1:


Here is some code I put together to get you started. Press the button to start the Timeline. Press left or right arrow key to move the circle. The Timeline loops every 16 millisec. That's close to 60 FPS. I would change the value to get it to about 40 FPS for a game like this. Here is a valuable resource. Here is another.

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);
    }

}

Code update after comment on 6/8/2019



来源:https://stackoverflow.com/questions/56502206/trying-to-make-the-shape-continuously-move-in-one-direction-with-arrow-keys

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!