【问题标题】:Moving Two Rectangles with keyboard in Javafx在 Javafx 中使用键盘移动两个矩形
【发布时间】:2016-08-18 14:51:02
【问题描述】:

我对编程很陌生,我一直在使用 JavaFX 开发一个两人乒乓球游戏。一名玩家使用 W/S 移动他的“桨”,另一名玩家使用向上/向下箭头移动他的“桨”。我一直遇到的问题是一次只有一名玩家可以移动他的桨。我不知道如何获得它,以便他们每个人都可以同时移动各自的桨。我有一个键盘事件处理程序控制两个桨,我认为这是问题所在。我做了两个单独的键盘处理程序,但我认为另一组问题是由内置的 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;
            }
        }

    }
};
}

【问题讨论】:

    标签: javafx keyboard-events


    【解决方案1】:

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

    要解决此问题,只需“记住”每个桨的所需运动并收听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;
                }
    
            }
        };
    }
    

    【讨论】:

    • 非常感谢。它有效,现在一切都说得通了哈哈。我一生都无法弄清楚如何使用 AnimationTimer。并感谢您提供额外的提示
    猜你喜欢
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 2014-06-28
    • 1970-01-01
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多