1

I am trying to detect the collision between two shapes in JavaFX, and this method is not working. I am retrieving the Nodes of the two shapes, and then using the intersects method to compare their locations. What can I change here? Thank you!

public void collisionDetection() {
        if (_circle.getNode().intersects(_square.getRect().getX(), _square.getRect().getY(), 100.0, 30.0)) {
        System.out.println("collision detected");
        }
    }
}
Ingrid
  • 161
  • 1
  • 2
  • 8
  • Can you examine this link: http://stackoverflow.com/questions/20840587/how-to-use-intersect-method-of-node-class-in-javafx – GltknBtn Jan 23 '17 at 08:41

2 Answers2

3

The answer to the other question referenced in the comments (How to use intersect() method of Node Class in JavaFX?) is inaccurate. The Node#intersects(Bounds) method does not take the local bounds of another node as input, but instead the bounds of another node within the local coordinate system of the calling node. Therefore, you need to transform the bounds in order to be able to detect collisions, as follows:

if (_circle.intersects(
        _circle.sceneToLocal(_square.localToScene(
            _square.getBoundsInLocal()))) {
    // ...
}
Community
  • 1
  • 1
Matthias
  • 1,005
  • 7
  • 20
2

I have created a collision detection app that you can play with to better understand collision detection.

Main:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 *
 * @author blj0011
 */
public class CollisionDection extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();
    }

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

}

FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.Double?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Polygon?>

<AnchorPane id="AnchorPane" fx:id="apMain" prefHeight="446.0" prefWidth="577.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111" fx:controller="collisiondection.FXMLDocumentController">
    <children>
        <Label fx:id="lblMain" layoutX="254.0" layoutY="408.0" minHeight="16" minWidth="69" />
      <Polygon fx:id="polyOne" fill="DODGERBLUE" layoutX="122.0" layoutY="166.0" stroke="BLACK" strokeType="INSIDE">
        <points>
          <Double fx:value="-50.0" />
          <Double fx:value="40.0" />
          <Double fx:value="50.0" />
          <Double fx:value="40.0" />
          <Double fx:value="0.0" />
          <Double fx:value="-60.0" />
        </points>
      </Polygon>
      <Polygon fx:id="polyTwo" fill="DODGERBLUE" layoutX="419.0" layoutY="166.0" stroke="BLACK" strokeType="INSIDE">
        <points>
          <Double fx:value="-50.0" />
          <Double fx:value="40.0" />
          <Double fx:value="50.0" />
          <Double fx:value="40.0" />
          <Double fx:value="0.0" />
          <Double fx:value="-60.0" />
        </points>
      </Polygon>
    </children>
</AnchorPane>

Controller:

import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Point2D;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Shape;

/**
 *
 * @author sedj601
 */
public class FXMLDocumentController implements Initializable {

    @FXML private Label lblMain;
    @FXML private Polygon polyOne, polyTwo;    

    final ObjectProperty<Point2D> mousePosition = new SimpleObjectProperty<>();

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
        polyOne.setOnMousePressed((MouseEvent event) -> {
            mousePosition.set(new Point2D(event.getSceneX(), event.getSceneY()));
        });

        polyOne.setOnMouseDragged((MouseEvent event) -> {
            double deltaX = event.getSceneX() - mousePosition.get().getX();
            double deltaY = event.getSceneY() - mousePosition.get().getY();
            polyOne.setLayoutX(polyOne.getLayoutX()+deltaX);
            polyOne.setLayoutY(polyOne.getLayoutY()+deltaY);
            mousePosition.set(new Point2D(event.getSceneX(), event.getSceneY()));

            Shape intersect = Shape.intersect(polyOne, polyTwo);

            if(intersect.getBoundsInLocal().getWidth() != -1)
            {
                System.out.println("This object can overlap other the other object!");
                lblMain.setText("Collision detected!");
            }
            else
            {
                intersect.getBoundsInLocal().getWidth();
                lblMain.setText("Collision not detected!");
            }            
        });

        polyTwo.setOnMousePressed((MouseEvent event) -> {
            mousePosition.set(new Point2D(event.getSceneX(), event.getSceneY()));
        });

        polyTwo.setOnMouseDragged((MouseEvent event) -> {
            double deltaX = event.getSceneX() - mousePosition.get().getX();
            double deltaY = event.getSceneY() - mousePosition.get().getY();
            polyTwo.setLayoutX(polyTwo.getLayoutX() + deltaX);
            polyTwo.setLayoutY(polyTwo.getLayoutY() + deltaY);
            mousePosition.set(new Point2D(event.getSceneX(), event.getSceneY()));

            Shape intersect = Shape.intersect(polyOne, polyTwo);
            {
                if(intersect.getBoundsInLocal().getWidth() != -1)
                {      
                    System.out.println("This object can not overlap other the other object!");
                    polyTwo.setLayoutX(polyTwo.getLayoutX() - deltaX);
                    polyTwo.setLayoutY(polyTwo.getLayoutY() - deltaY);
                    lblMain.setText("Collision detected!");
                }
                else
                {
                    lblMain.setText("Collision not detected!");
                }
            }
        });   
    }
}
SedJ601
  • 12,173
  • 3
  • 41
  • 59
  • 1
    The left node will detect collision when dragged into the other node, and will overlap the other node. The right node will detect collision when dragged but will not overlap the other node. – SedJ601 Jan 23 '17 at 15:37