Sean
Sean

Reputation: 21

Circle movement upon rectangle Collision

I'm working on understanding collision detection and movement and I am having issues getting the movement down correctly. my goal is to allow a player to move around rectangles but not through them. my problem is that once the player reaches the bounds of the rectangle they are unable to backup. any help would be greatly appreciated.

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

    }
}

Upvotes: 2

Views: 361

Answers (1)

SedJ601
SedJ601

Reputation: 13859

Since you are using Shape, it's a good idea to use Shape.intersect(player, r1).getBoundsInLocal().getWidth() != -1 to detect intersection. Also, instead of using player.centerYProperty().setValue(...);, just use player.setCenterY(...). You had a couple more problems, but the most important one is the idea of what to do once an intersection is detected. Once an intersection is detected you should go back to the distance just before the detection(only if you are moving in small enough steps).

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

    }
}

Upvotes: 2

Related Questions