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

如何在翻译转换(JavaFX)中实现冲突检测?

龚宏壮
2023-03-14

我写了下面的JavaFX程序,其中两个矩形节点正在转换转换:

public class Test extends Application{
public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception {
    BorderPane borderPane = new BorderPane();
    borderPane.setStyle("-fx-background-color: green;");


    Rectangle rect1 = new Rectangle(20,20,50, 50);
    rect1.setArcHeight(15);
    rect1.setArcWidth(15);
    rect1.setFill(Color.RED);

    Rectangle rect2 = new Rectangle(20,20,30, 30);
    rect2.setArcHeight(15);
    rect2.setArcWidth(15);
    rect2.setFill(Color.RED);

    TranslateTransition translateTransition1 = new TranslateTransition(Duration.millis(2000), rect1);
    translateTransition1.setFromX(0);
    translateTransition1.setToX(300);
    translateTransition1.setToY(300);
    translateTransition1.setCycleCount(Timeline.INDEFINITE);
    translateTransition1.setAutoReverse(true);
    translateTransition1.play();

   TranslateTransition translateTransition2 = new TranslateTransition(Duration.millis(2000), rect2);
   translateTransition2.setFromX(300);
   translateTransition2.setToX(0);
   translateTransition2.setToY(300);
   translateTransition2.setCycleCount(Timeline.INDEFINITE);
   translateTransition2.setAutoReverse(true);
   translateTransition2.play();


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

    primaryStage.setScene(new Scene(borderPane, 500, 500));
    primaryStage.show();

  }

}

如何对“平移转换”中的两个矩形节点实施冲突检测?

共有3个答案

韦安顺
2023-03-14

编辑:做了一些简单的修改,采用基于状态的方法,代码已经更新。

好吧,我的方法是不同的,以上所有。。。

注意:我使用的是1.8源代码

我创建了一个Colliable接口:

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.shape.Shape;

public interface Collidable{
    public enum CollisionState{
        WAITING,
        TOUCHING;        
    }

    ObjectProperty<CollisionState> state = new SimpleObjectProperty<>(CollisionState.WAITING);
    public default ReadOnlyObjectProperty<CollisionState> collisionStateProperty(){return state;}
    public default CollisionState getCollisionState(){return state.get();}

    BooleanProperty collided = new SimpleBooleanProperty(false){{
            addListener((ObservableValue<? extends Boolean> observable1, Boolean oldValue, Boolean touching) -> {
                if(touching){
                    state.set(CollisionState.TOUCHING);
                }else{
                    state.set(CollisionState.WAITING);
                }
            });
    }};
    public default boolean hasCollided(){return collided.get();}
    public default BooleanProperty collidedProperty(){return collided;}

    public default void checkCollision(Shape src, Shape other){
        if(Shape.intersect(src, other).getBoundsInLocal().getWidth() > -1 && !getCollisionState().equals(CollisionState.TOUCHING)){
            collided.set(true); 
            handleCollision(other);
        }else if(Shape.intersect(src, other).getBoundsInLocal().getWidth() <= 0){
            collided.set(false);            
        }
    }

    public void handleCollision(Shape other);

}

以及简单的实现:

import javafx.animation.Animation;
import javafx.animation.ParallelTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 *
 * @author Dub-Laptop
 */
public class CollisionTesting extends Application {

    private TranslateTransition cAnim;

    @Override
    public void start(Stage primaryStage) {        

        Group root = new Group();

        Scene scene = new Scene(root);

        primaryStage.setTitle("Collision Testing");
        primaryStage.setScene(scene);
        primaryStage.show();

        Rectangle r = new Rectangle(100,50, Color.AQUA);
        r.setLayoutX(10);
        r.setLayoutY(200);

        CollidableCircle c = new CollidableCircle(50, Color.GREEN);
        c.setLayoutX(800);
        c.setLayoutY(200);

        /* can change this to anything you like 
           I used translateXProperty for simplicity
        */                                  
        c.translateXProperty().addListener((Observable observable) -> {
            c.checkCollision(c, r);
        });

        root.getChildren().addAll(r, c);

        TranslateTransition rAnim = new TranslateTransition();

        rAnim.setToX(600);
        rAnim.setAutoReverse(true);
        rAnim.setCycleCount(Animation.INDEFINITE);
        rAnim.setDuration(Duration.seconds(5));
        rAnim.setNode(r);

        cAnim = new TranslateTransition();

        cAnim.setToX(-590);
        cAnim.setAutoReverse(true);
        cAnim.setCycleCount(Animation.INDEFINITE);
        cAnim.setDuration(Duration.seconds(5));
        cAnim.setNode(c);

        rAnim.play();
        cAnim.play();
    }

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

    private class CollidableCircle extends Circle implements Collidable{

        public CollidableCircle(double radius, Paint fill) {
            super(radius, fill);
            new AnimationTimer(){
                @Override
                public void handle(long now) {
                    root.getChildren().filtered((Node n)->{
                        return !n.equals(CollidableCircle.this) && n instanceof Shape;
                    }).forEach(other ->{
                        checkCollision(CollidableCircle.this, (Shape)other);
                    });
                }
            }.start();
            // I added this for local property changes to this node
            collisionStateProperty().addListener((ObservableValue<? extends CollisionState> observable, CollisionState oldValue, CollisionState newValue) -> {
                if(newValue.equals(CollisionState.TOUCHING)){  
                    setScaleX(1.25);
                    setScaleY(1.25);
                    setFill(Color.GREENYELLOW);
                    cAnim.pause();
                }else if(newValue.equals(CollisionState.WAITING)){      
                    setScaleX(1.0);
                    setScaleY(1.0);
                    setFill(Color.GREEN);
                    cAnim.play();
                }
            });
        }

        @Override
        public void handleCollision(Shape other) {            
           // handle updates that affect other node here
           System.out.println("Collided with : " + other.getClass().getSimpleName());
        }

    }    

}

IMHO不使用边界来检查形状碰撞,而是使用布尔:

(Shape.intersect(s1,s2)。getBoundsInLocal()。getWidth()

这种方法对于形状更精确,因为它将检查形状边界内的非空像素,而不是正常的矩形边界。

但是,如果您真的想使用边界,这也应该起作用:

if(sourceShape.getBoundsInLocal().intersects(otherShape.getBoundsInParent()){
    Shape intersect = Shape.intersect(sourceShape, otherShape);
    if(intersect.getBoundsInLocal().getWidth > -1){
        // handle code here
    }
}

但是,正如您所看到的,它更加冗长,实际上与我的其他方法相同。

希望这有帮助。

贺宏富
2023-03-14

翻译翻译并不意味着支持冲突检测。它只是将A移动到B,而不考虑除其节点之外的任何东西的状态。

您需要一个Tranection机制来感知板上的其他对象。

好消息是创建Tranection并不难。您可以创建一个继承Tranature的类并简单地实现interpolate()方法。

从JavaDoc:

下面是一个简单的示例。它创建一个小动画来更新Text节点的text属性。它从一个空字符串开始,然后逐个字母逐渐添加,直到动画结束时设置完整的字符串。

 final String content = "Lorem ipsum";
 final Text text = new Text(10, 20, "");

 final Animation animation = new Transition() {
     {
         setCycleDuration(Duration.millis(2000));
     }

     protected void interpolate(double frac) {
         final int length = content.length();
         final int n = Math.round(length * (float) frac);
         text.setText(content.substring(0, n));
     }

 };

坏消息是,拥有一个成功的碰撞检测机制有点困难。我真的不是这方面的专家,但我可能会有一个<code>ObservableList

如果你想要比这更好的东西,你可能会想看看像Slick2D这样的2D游戏框架。

燕承安
2023-03-14

对于矩形,这很容易;只需在父属性中获取它们的边界并查看它们是否相交。唯一的缺点是它没有考虑弯曲的角:如果您想要达到这种精度水平,您可能需要手动计算。对于非矩形形状,您也可以只观察父属性中的边界,但您需要手动计算以查看形状是否相交。

    ObservableBooleanValue colliding = Bindings.createBooleanBinding(new Callable<Boolean>() {

        @Override
        public Boolean call() throws Exception {
            return rect1.getBoundsInParent().intersects(rect2.getBoundsInParent());
        }

    }, rect1.boundsInParentProperty(), rect2.boundsInParentProperty());

    colliding.addListener(new ChangeListener<Boolean>() {
        @Override
        public void changed(ObservableValue<? extends Boolean> obs,
                Boolean oldValue, Boolean newValue) {
            if (newValue) {
                System.out.println("Colliding");
            } else {
                System.out.println("Not colliding");
            }
        }
    });
 类似资料:
  • 我正在尝试检查StackPane中节点的冲突检测。下面是我的代码: 在这里,如果我使用AnchorPane,碰撞检测就会工作。但在StackPane的情况下,我无法做到这一点。我猜这是因为堆栈窗格的坐标系统(如果我错了,请纠正我)。 所以请帮我实现上述两个矩形的碰撞检测。另外,如果我想更改节点的坐标,请提供一些建议(如果您知道),以便在StackPane内的节点上实现此类冲突检测。

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

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

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

  • 问题内容: 当使用英雄图像或全屏显示时,我通常会看到带有以下CSS的文本或图像: 有人可以向我解释此代码的实际作用吗? 问题答案: 之所以需要这样做,是因为您希望 元素 的中心与父 元素 的中心对齐。简单来说,可以归结为,这意味着: 沿x轴向左移动我宽度的50%,并且 沿y轴将我向上移动我身高的50% 这有效地将元素的中心移动到其原始的左上角。请记住,而不是在元素上进行设置时,您要将其左上角移至其