javafx - 矩形碰撞时的圆运动

标签 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);

    }
}

最佳答案

由于您使用的是 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);

    }
}

关于javafx - 矩形碰撞时的圆运动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47635541/

相关文章:

JavaFX 视频在反复播放同一视频几个小时后出现卡顿

Python 和 Pygame : Ball collision with interior of circle

javascript - Leaflet.js - 我可以在单个多边形内添加多个孔/切口吗

java - 在 javafx 中选择不同选项卡时更改阶段 titleProperty

可编辑单元格上的 JavaFX 工具提示

c# - 如何在类似 Space Invaders 的游戏中执行子弹/敌人矩形碰撞检测?

android - 如何创建内部路径透明的矢量绘图?

css - 创建特殊的 CSS 形状

java - 如何使用动态生成的不同类型的列创建表格 View ?

java - 处理浮点精度问题(测试与SAT的碰撞)