如何在StackPane(在JavaFX中)的节点上实现冲突检测?

时间:2014-01-29 06:58:19

标签: javafx javafx-2 collision-detection javafx-8

我正在尝试检查StackPane内部节点上的冲突检测。以下是我的代码:

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

如果我使用AnchorPane,碰撞检测正在运行。但是使用StackPane我无法实现它。我想这是因为堆栈窗格的坐标系统(如果我错了,请纠正我)。

所以请帮我实现上述两个矩形的碰撞检测。如果我想更改节点的坐标,请提供一些建议(如果您知道的话)在StackPane内的节点上实现此类冲突检测。

2 个答案:

答案 0 :(得分:6)

在测试条件下,将一个矩形的局部边界与另一个矩形的父边界进行比较。您想要比较相同的边界类型。

所以改变:

rect1.intersects(newValue)

要:

rect1.getBoundsInParent().intersects(newValue)

要更好地理解边界类型,您可能想要使用此intersection demo application.

答案 1 :(得分:1)

根据我的经验,如果创建一个环境(碰撞空间),应该使用一个组而不是容器..

我认为在你的情况下,stackPane是罪魁祸首。

加上我认为你的碰撞检查应该更符合这一点:

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

或者你可以在这些方面做更多的事情:在一个扩展“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
        }
    }
}
好吧那就是我的2美分......

我刚注意到的另一件事是,每次调用check碰撞方法时都注册一个新的changeListener而没有注册它...这可能会导致以后出现问题......