矩形碰撞时的圆周运动

时间:2017-12-04 14:28:10

标签: javafx collision-detection shapes

我正在努力了解碰撞检测和移动,我遇到了正确降低移动的问题。我的目标是允许玩家在矩形周围移动而不是通过它们移动。我的问题是,一旦玩家到达矩形的边界,他们就无法备份。任何帮助将不胜感激。

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import static javafx.scene.input.KeyCode.DOWN;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Circle;

public class CircleMovement extends Application {

    //create the panes to handle the game
    BorderPane mainPane = new BorderPane();
    GridPane infoPane = new GridPane();
    Pane gameField = new Pane();
    Scene scene;
    //create circle/movement properties
    double increment = 5.0;
    double radius = 10;
    double x = radius, y = radius;
    //create Rectangle properties
    double Rwidth = 80;
    double Rheight = 20;
    //create player and objects
    Circle player = new Circle(x, y, radius);
    Rectangle r1 = new Rectangle(0, 100, Rwidth, Rheight);//Rectangle(int x, int y, int width, int height)

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

    @Override
    public void start(Stage stage) throws Exception {
        setPanes();
        gameField.getChildren().addAll(r1, player);
        moveCircleOnKeyPress(scene, player);//pass to player movement method

        //set the stage
        stage.setScene(scene);
        stage.show();
    }

    public void moveCircleOnKeyPress(Scene scene, Circle player) {//player movement
        scene.setOnKeyPressed((KeyEvent event) -> {
            switch (event.getCode()) {
                case UP:
                    player.setCenterY(player.getCenterY() - increment);//move player
                    if (player.getBoundsInLocal().intersects(r1.getBoundsInLocal())) {
                        player.centerYProperty().setValue(r1.getY());
                    }
                    break;
                case RIGHT:
                    player.setCenterX(player.getCenterX() + increment);
                    if (player.getBoundsInLocal().intersects(r1.getBoundsInLocal())) {
                        player.centerYProperty().setValue(r1.getY());
                    }
                    break;
                case DOWN:
                    player.setCenterY(player.getCenterY() + increment);
                    if (player.getBoundsInLocal().intersects(r1.getBoundsInLocal())) {
                        player.centerYProperty().setValue(r1.getY());
                    }
                    break;
                case LEFT:
                    player.setCenterX(player.getCenterX() - increment);
                    if (player.getBoundsInLocal().intersects(r1.getBoundsInLocal())) {
                        player.centerYProperty().setValue(r1.getY());
                    }
                    break;
            }
        });
    }

    public void setPanes() {
        infoPane.setMaxSize(200, 200);
        mainPane.setMaxSize(800, 800);
        mainPane.setCenter(gameField);//place the main game inside the center
        mainPane.setRight(infoPane);
        mainPane.setPadding(new Insets(10, 10, 10, 10));
        mainPane.setStyle("-fx-border-color: red");
        gameField.setStyle("-fx-background-color: white");
        gameField.setStyle("-fx-border-color: black");
        gameField.setMaxSize(600, 600);
        scene = new Scene(mainPane, 800, 800);
        player.setFill(Color.RED);

    }
}

1 个答案:

答案 0 :(得分:2)

由于您使用Shape,因此使用Shape.intersect(player, r1).getBoundsInLocal().getWidth() != -1检测交叉点是个不错的主意。另外,请使用player.centerYProperty().setValue(...);,而不是使用player.setCenterY(...)。你还有几个问题,但最重要的一个是在检测到交叉点后该做什么的想法。一旦检测到交叉路口,您应该回到检测前的距离(仅当您以足够小的步幅移动时)。

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import static javafx.scene.input.KeyCode.DOWN;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;

public class CircleMovement extends Application
{

    //create the panes to handle the game
    BorderPane mainPane = new BorderPane();
    GridPane infoPane = new GridPane();
    Pane gameField = new Pane();
    Scene scene;
    //create circle/movement properties
    double increment = 5.0;
    double radius = 10;
    double x = radius, y = radius;
    //create Rectangle properties
    double Rwidth = 80;
    double Rheight = 20;
    //create player and objects
    Circle player = new Circle(x, y, radius);
    Rectangle r1 = new Rectangle(0, 100, Rwidth, Rheight);//Rectangle(int x, int y, int width, int height)

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

    @Override
    public void start(Stage stage) throws Exception
    {
        setPanes();
        gameField.getChildren().addAll(r1, player);
        moveCircleOnKeyPress(scene, player);//pass to player movement method

        //set the stage
        stage.setScene(scene);
        stage.show();
    }

    public void moveCircleOnKeyPress(Scene scene, Circle player)
    {//player movement
        scene.setOnKeyPressed((KeyEvent event) ->
        {
            switch (event.getCode())
            {
                case UP:
                    player.setCenterY(player.getCenterY() - increment);//move player
                    //if (player.getBoundsInLocal().intersects(r1.getBoundsInLocal()))
                    if (Shape.intersect(player, r1).getBoundsInLocal().getWidth() != -1)
                    {
                        player.setCenterY(player.getCenterY() + increment);
                    }
                    break;
                case RIGHT:
                    player.setCenterX(player.getCenterX() + increment);

                    if (Shape.intersect(player, r1).getBoundsInLocal().getWidth() != -1)
                    {
                        player.setCenterX(player.getCenterX() - increment);
                    }
                    break;
                case DOWN:
                    player.setCenterY(player.getCenterY() + increment);
                    if (Shape.intersect(player, r1).getBoundsInLocal().getWidth() != -1)
                    {
                        player.setCenterY(player.getCenterY() - increment);
                    }
                    break;
                case LEFT:
                    player.setCenterX(player.getCenterX() - increment);
                    if (Shape.intersect(player, r1).getBoundsInLocal().getWidth() != -1)
                    {
                        player.setCenterX(player.getCenterX() + increment);
                    }
                    break;
            }
        });
    }

    public void setPanes()
    {
        infoPane.setMaxSize(200, 200);
        mainPane.setMaxSize(800, 800);
        mainPane.setCenter(gameField);//place the main game inside the center
        mainPane.setRight(infoPane);
        mainPane.setPadding(new Insets(10, 10, 10, 10));
        mainPane.setStyle("-fx-border-color: red");
        gameField.setStyle("-fx-background-color: white");
        gameField.setStyle("-fx-border-color: black");
        gameField.setMaxSize(600, 600);
        scene = new Scene(mainPane, 800, 800);
        player.setFill(Color.RED);

    }
}