当前位置: 首页 > 知识库问答 >
问题:

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

上官修文
2023-03-14

我正在尝试检查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个答案

夏侯兴怀
2023-03-14

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

我认为在你的情况下,堆栈窗格是罪魁祸首。

此外,我认为您的碰撞检查应该更符合以下内容:

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-collistener方法时,您都会注册一个新的changeListener,而不会取消注册。这可能会导致以后出现问题。。。

堵德曜
2023-03-14

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

因此,改变:

rect1.intersects(newValue)

自:

rect1.getBoundsInParent().intersects(newValue)

为了更好地理解边界类型,您可能希望使用此交集演示应用程序。

 类似资料:
  • 作为前言,我对JavaFX编程非常陌生。(我们上学期在我的一堂课上介绍了JavaFX,在过去的一个月左右的时间里,我一直在努力用JavaFX制作一个简单的游戏。 我遇到的一个问题是试图检测一个StackPane中的窗格与另一个StackPane中的窗格的冲突。具体来说,我在Game类中有一个“Player”节点(“Player”扩展了抽象的“Sprite ”,后者扩展了StackPane)以及一些

  • 我写了下面的JavaFX程序,其中两个矩形节点正在转换转换: 如何对“平移转换”中的两个矩形节点实施冲突检测?

  • 我使用下面的类制作了一个项目符号列表和一个精灵列表。如何检测子弹是否与子画面发生碰撞,然后删除该精灵和子弹?

  • 我目前正在为一个学校项目制作一个小游戏,冲突检测有问题。 这是我的时间线和跳转按钮代码: 这是我对碰撞检测的尝试: 我只能假设这不起作用,因为它不会不断地寻找X和Y位置,但我不确定如何做到这一点。

  • 我有一个BufferedImage,我想在stackpane中显示,因为我在JavaFX应用程序中工作。几天前我也处于同样的情况,但我在Java工作,在这种情况下,我喜欢这样: ... 该方法继续使用其他代码,但目前并不重要。所以,在Java我用图像创建一个Jtag,然后添加到Jframe。我必须在JavaFX中做什么才能在Stackpane中显示图片?我尝试了其中是一个stackpane,但它不

  • 我们可以在unity3d中检测网格碰撞吗?我想在碰撞时显示一些纹理,目前我正在使用箱形碰撞体,这就是为什么它的表面/边缘与对象体网格不匹配的原因,即使我在网格表面上获得命中点,我也不知道如何在网格上的特定位置将纹理放在网格上, 在unity3d中,是否有任何特定于相同类型要求的内置组件或解决方法? 正如我们在图片中看到的,在游戏对象内检测到了碰撞,因为框碰撞器位于目标对象网格内。注意:这里我用虚拟