How to implement collision detection on nodes which are in StackPane (in JavaFX)?


Question

I am trying to check collision detection on the nodes which are inside StackPane. Below is my code:

public void start(Stage primaryStage) throws Exception {
    StackPane pane = new StackPane();
    Scene scene = new Scene(pane,300,300,Color.GREEN);
    primaryStage.setScene(scene);       
    primaryStage.show();

    Rectangle  rect1 = new Rectangle(50, 50);
    rect1.setFill(Color.BLUE);
    Rectangle rect2 = new Rectangle(50, 50);         

    pane.getChildren().add(rect1);
    pane.getChildren().add(rect2);

    TranslateTransition translateTransitionEnemyCar = new TranslateTransition();
    translateTransitionEnemyCar.setDuration(Duration.millis(2000));
    translateTransitionEnemyCar.setNode(rect2);
    translateTransitionEnemyCar.setFromY(-150);
    translateTransitionEnemyCar.setToY(150);
    translateTransitionEnemyCar.setAutoReverse(true);
    translateTransitionEnemyCar.setCycleCount(Timeline.INDEFINITE);
    translateTransitionEnemyCar.play();             
    checkCollision(pane,rect1,rect2);       
}

//Collision Detection
 void checkCollision(StackPane pane, final Rectangle rect1, Rectangle rect2){   

     rect2.boundsInParentProperty().addListener(new ChangeListener<Bounds>() {
        @Override
        public void changed(ObservableValue<? extends Bounds> arg0,Bounds oldValue, Bounds newValue) {
            if(rect1.intersects(newValue)){
                System.out.println("Collide ============= Collide");
            }
        }
    });
 }
}

Here the collision detection is working if I use AnchorPane. But with StackPane I am not able to achieve it. I guess it is because of the co-ordinate system of the stack pane (Correct me if I am wrong).

So please help me out to achieve collision detection of the above two rectangles. Also please provide some suggestion (if you know) to implement such collision detection on nodes inside StackPane if I want to change the the co-ordinate of the nodes.

1
2
1/29/2014 6:58:18 AM

Accepted Answer

In your test condition you compare the local bounds of one rectangle with the bounds in parent of the other rectangle. You want to compare the same bounds types.

So change:

rect1.intersects(newValue)

To:

rect1.getBoundsInParent().intersects(newValue)

To understand bounds types better, you might want to play with this intersection demo application.

6
1/29/2014 8:33:50 AM

Well in My experience, if creating an environment (collision space) a group should be used as opposed to a container..

I think in your situation the stackPane is the culprit.

plus I think your collision check should be more along the lines of this:

public void checkCollisions(){
    if(rect1.getBoundsInParent().intersects(rect2.getBoundsInParent)){
        Shape intersect = Shape.intersect(rect1, rect2);
        if(intersect.getBoundsInLocal().getWidth() != -1){
            // Collision handling here
            System.out.println("Collision occured");
        }
    }
}

Or you could do something more along these lines: in a class that extends "Node"

public boolean collided(Node other) {
    if(this.getBoundsInParent().intersects(other.getBoundsInParent())){
        Shape intersect = Shape.intersect(this.getShape(), other.getShape());
        if(intersect.getBoundsInLocal().getWidth() != -1){                
            System.out.println(this.getId() + " : " + other.getId());                 
            return true;
        }
    }        
    return false;        
}
public void checkCollisions(){
    for(Node n : root.getChildren().filtered(new Predicate(){
        @Override
        public boolean test(Object t) {
            //makes sure object does not collide with itself
            return !t.equals(this);
            // for shapes
            // return t instanceof Shape;  
        }
    }){
        if(collided(n)){
            // handle code here
        }
    }
}

well thats my 2 cents...

Another thing i just noticed is you are registering a new changeListener each time your check collision method is called without un-registering it.. that could lead to problems later imo...


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon