在Javafx中使用键盘移动两个矩形

时间:2016-08-17 22:46:00

标签: javafx keyboard-events

我对编程很新,而且我一直在使用JavaFX进行双人Pong游戏。一名玩家使用W / S移动他的"桨#34;而其他玩家使用向上/向下箭头。我一直存在的问题是只有一名球员可以一次移动他的球拍。我无法弄清楚如何获得它,以便他们可以同时移动他们的单个拨片。我有一个键盘事件处理程序控制两个拨片,我认为这是问题。我制作了两个单独的键盘处理程序,但是我认为是由内置的setFocusTraversable方法引起的另一组问题。我希望我尝试做的事情有道理。有什么想法吗?

import javafx.event.EventHandler;
import javafx.scene.Group;
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.scene.paint.Paint;
import javafx.scene.shape.Rectangle;


public class Game{

Rectangle leftPaddle;
double leftPaddleY = 260;

Rectangle rightPaddle;
double rightPaddleY = 260;

public void createGame(Group gameDisplay){

    //creates background
    Rectangle background = new Rectangle(0,0,800,600);
    background.getStyleClass().add("background");

    //draws field lines
    Canvas game = new Canvas(800, 600);
    GraphicsContext gc = game.getGraphicsContext2D();
    gc.setStroke(Paint.valueOf("WHITE"));
    gc.setLineWidth(5);
    gc.strokeLine(400, 0, 400, 600);
    gc.strokeOval(300, 200, 200, 200);
    gc.strokeRect(0, 150, 100, 300);
    gc.strokeRect(700, 150, 100, 300);
    gc.setStroke(Paint.valueOf("BLACK"));
    gc.setLineWidth(8);
    gc.strokeRect(0, 0, 800, 600);

    //creates red paddle
    leftPaddle = new Rectangle(30, leftPaddleY, 20, 70);
    leftPaddle.setOnKeyPressed(paddleMovement);
    leftPaddle.setFocusTraversable(true);
    leftPaddle.setFill(Color.RED);

    //creates blue paddle
    rightPaddle = new Rectangle(750, rightPaddleY, 20, 70);
    rightPaddle.setOnKeyPressed(paddleMovement);
    rightPaddle.setFocusTraversable(true);
    rightPaddle.setFill(Color.BLUE);


    gameDisplay.getStylesheets().add(getClass().getResource("GameDisplay.css").toExternalForm());
    gameDisplay.getChildren().addAll(background, game, leftPaddle, rightPaddle);
}

public EventHandler<KeyEvent> paddleMovement = new EventHandler<KeyEvent>(){

    @Override
    public void handle(KeyEvent event) {

        //red paddle movement
        if(event.getCode().equals(KeyCode.W)){
            leftPaddle.setY(leftPaddleY -= 6);
            if(leftPaddle.getY() < 0){
                leftPaddle.setY(0);
                leftPaddleY = 0;
            }
        }
        if(event.getCode().equals(KeyCode.S)){
            leftPaddle.setY(leftPaddleY += 6);
            if(leftPaddle.getY() < 0){
                leftPaddle.setY(0);
                leftPaddleY = 0;
            }
        }

        //blue paddle movement
        if(event.getCode().equals(KeyCode.UP)){
            rightPaddle.setY(rightPaddleY -= 6);
            if(rightPaddle.getY() < 0){
                rightPaddle.setY(0);
                rightPaddleY = 0;
            }
        }
        if(event.getCode().equals(KeyCode.DOWN)){
            rightPaddle.setY(rightPaddleY += 6);
            if(rightPaddle.getY() < 0){
                rightPaddle.setY(0);
                rightPaddleY = 0;
            }
        }

    }
};
}

1 个答案:

答案 0 :(得分:2)

只有在按下最后一个键时才会重复触发keyPressed事件。

要解决这个问题,请记住&#34;每个拨片的所需移动并听取keyReleased事件。您可以使用AnimationTimer执行移动以每帧执行更新(您也可以使用Timeline来更好地控制更新的频率。)

此外,我建议对成员变量的可见性进行更严格的限制,因为通常您不希望其他类能够直接写入您的类的字段。另外,我建议在单个Node中处理事件。一次只有一个Node可以拥有焦点,并且在不同的地方处理事件只会导致代码重复。

public class Game {

    private Rectangle leftPaddle;
    private double leftPaddleY = 260;

    private Rectangle rightPaddle;
    private double rightPaddleY = 260;

    private double leftPaddleDY;
    private double rightPaddleDY;
    private AnimationTimer timer = new AnimationTimer() {

        @Override
        public void handle(long now) {
            // update paddle positions
            leftPaddleY += leftPaddleDY;
            rightPaddleY += rightPaddleDY;
            if (leftPaddleY < 0) {
                leftPaddleY = 0;
            }
            if (rightPaddleY < 0) {
                rightPaddleY = 0;
            }

            leftPaddle.setY(leftPaddleY);
            rightPaddle.setY(rightPaddleY);
        }

    };

    public void createGame(Group gameDisplay) {

        //creates background
        Rectangle background = new Rectangle(0, 0, 800, 600);
        background.getStyleClass().add("background");

        //draws field lines
        Canvas game = new Canvas(800, 600);
        GraphicsContext gc = game.getGraphicsContext2D();
        gc.setStroke(Paint.valueOf("WHITE"));
        gc.setLineWidth(5);
        gc.strokeLine(400, 0, 400, 600);
        gc.strokeOval(300, 200, 200, 200);
        gc.strokeRect(0, 150, 100, 300);
        gc.strokeRect(700, 150, 100, 300);
        gc.setStroke(Paint.valueOf("BLACK"));
        gc.setLineWidth(8);
        gc.strokeRect(0, 0, 800, 600);

        //creates red paddle
        leftPaddle = new Rectangle(30, leftPaddleY, 20, 70);
        leftPaddle.setFill(Color.RED);

        //creates blue paddle
        rightPaddle = new Rectangle(750, rightPaddleY, 20, 70);
        rightPaddle.setFill(Color.BLUE);

        // register event handlers to Canvas
        game.setFocusTraversable(true);
        game.setOnKeyPressed(keyPressed);
        game.setOnKeyReleased(keyReleased);

        gameDisplay.getStylesheets().add(getClass().getResource("GameDisplay.css").toExternalForm());
        gameDisplay.getChildren().addAll(background, game, leftPaddle, rightPaddle);
        // start updates of paddle positions
        timer.start();
    }

    private EventHandler<KeyEvent> keyReleased = new EventHandler<KeyEvent>() {

        @Override
        public void handle(KeyEvent event) {
            // set movement to 0, if the released key was responsible for the paddle
            switch (event.getCode()) {
                case W:
                case S:
                    leftPaddleDY = 0;
                    break;
                case UP:
                case DOWN:
                    rightPaddleDY = 0;
                    break;
            }
        }

    };

    private EventHandler<KeyEvent> keyPressed = new EventHandler<KeyEvent>() {

        @Override
        public void handle(KeyEvent event) {
            // start movement according to key pressed
            switch (event.getCode()) {
                case W:
                    leftPaddleDY = -6;
                    break;
                case S:
                    leftPaddleDY = 6;
                    break;
                case UP:
                    rightPaddleDY = -6;
                    break;
                case DOWN:
                    rightPaddleDY = 6;
                    break;
            }

        }
    };
}