JavaFX: How to move 2 Rectangles at the same time?

2020-04-14 12:39发布

问题:

I have 2 rectangles representing the paddles for my Pong game. I use W/S for one rectangle and UP/DOWN for the second rectangle. When I press W to move one rectangle and then press UP to move the second rectangle, the first rectangle will stop moving and then the second rectangle will move. How do I make it so both rectangles can move simultaneously?

GraphicsContext gc;


Rectangle player11;
Rectangle player22;
Circle ball;
private int y1;
private int p1y = 381;
private int y2;
private int p2y = 381;
AnimateObjects animate;
Canvas canvas;

private AnimationTimer timer = new AnimationTimer() {
    public void handle(long now) {
        // update paddle positions
        p1y += y1;
        p2y += y2;
        if (p1y < 0) {
            p1y = 0;
        }
        if (p2y < 0) {
            p2y = 0;
        }

        player11.setY(p1y);
        player22.setY(p2y);
    }
};

public EventHandler<KeyEvent> keyReleased = new EventHandler<KeyEvent>() {
    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:
                y1 = 0;
                break;
            case UP:
            case DOWN:
                y2 = 0;
                break;
        }
    }
};

private EventHandler<KeyEvent> keyPressed = new EventHandler<KeyEvent>() {
    public void handle(KeyEvent event) {
        // start movement according to key pressed
        switch (event.getCode()) {
            case W:
                y1 = -6;
                break;
            case S:
                y1 = 6;
                break;
            case UP:
                y2 = -6;
                break;
            case DOWN:
                y2 = 6;
                break;
        }
    }
};

public static void main(String[] args) {
        launch();
}//main

public void start(Stage stage) {
    stage.setTitle("Pong");
    Group root = new Group();
    canvas = new Canvas(1000, 800);
    root.getChildren().add(canvas);
    Scene scene = new Scene(root, Color.GREEN);
    stage.setScene(scene);

    player11 = new Rectangle(30, p1y, 20, 70);
    player11.setFill(Color.RED);
    player22 = new Rectangle(750, p2y, 20, 70);
    player22.setFill(Color.BLUE);

    root.getChildren().add(player11);
    root.getChildren().add(player22);

    scene.setOnKeyPressed(keyPressed);
    scene.setOnKeyReleased(keyReleased);

    ball = new Circle(10, Color.DARKSLATEBLUE);
    root.getChildren().add(ball);
    ball.relocate(500,350);

    gc = canvas.getGraphicsContext2D();

    animate = new AnimateObjects();
    animate.start();

    stage.show();
}//start

public class AnimateObjects extends AnimationTimer {
    public void handle(long now) {
    }//handle method in AnimateObjects class
}//AnimateObjects class

}//pong class

回答1:

You need to capture KeyCodes. Use up, down, z, and x to control paddles. More comments in the code! Here is a working example.

import java.util.HashSet;
import java.util.Set;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
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.Rectangle;
import javafx.stage.Stage;

/**
 *
 * @author blj0011
 */
public class JavaFXApplication124 extends Application
{
   Rectangle leftPaddle, rightPaddle;
   AnimationTimer gameLoop;
   Set<KeyCode> input;
   Pane gameBoard;

    @Override
    public void start(Stage primaryStage)
    {        
        leftPaddle = new Rectangle(7, 100, Color.BLACK);
        leftPaddle.setX(3);
        leftPaddle.setY(0);

        rightPaddle = new Rectangle(7, 100, Color.BLACK);
        rightPaddle.setX(500 - 10);
        rightPaddle.setY(0);

        input = new HashSet(); //This set is used to keep up with keys that are currently being pressed.

        gameBoard = new Pane(leftPaddle, rightPaddle);
        VBox.setVgrow(gameBoard, Priority.ALWAYS);
        gameBoard.setOnKeyPressed(event -> input.add(event.getCode()));//add keys that are currently being pressed to the set
        gameBoard.setOnKeyReleased(event -> input.remove(event.getCode()));//remove keys from the set after they are released

        gameLoop = new AnimationTimer() {
            @Override
            public void handle(long l) {                
                movePaddle();//Call method to move paddle based on certain keys in the set
                System.out.println("playing");
            }
        };

        Button btnStartGame = new Button("Play");
        btnStartGame.setOnAction((event) -> {
            gameBoard.requestFocus();//Request gameboard focus to capture keyevents
            gameLoop.start();
            btnStartGame.setDisable(true);
        });

        VBox root = new VBox(gameBoard, btnStartGame);
        Scene scene = new Scene(root, 500, 500);



        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        launch(args);
    }

    //Use to move paddles based on keycodes in set
    private void movePaddle()
    {
        if (input.contains(KeyCode.UP)) {
            rightPaddle.setY(rightPaddle.getY() - 10);
        }
        else if (input.contains(KeyCode.DOWN)) {
            rightPaddle.setY(rightPaddle.getY() + 10);
        }

        if (input.contains(KeyCode.Z)) {
            leftPaddle.setY(leftPaddle.getY() - 10);
        }
        else if (input.contains(KeyCode.X)) {
            leftPaddle.setY(leftPaddle.getY() + 10);
        }
    }
}