Javafx 2 使用JavaFX检查形状冲突

Javafx 2 使用JavaFX检查形状冲突,javafx-2,javafx,collision-detection,Javafx 2,Javafx,Collision Detection,我正在尝试做一些碰撞检测。对于这个测试,我使用简单的矩形形状,并检查它们的边界,以判断它们是否发生碰撞。虽然检测没有按预期工作。我尝试过使用不同的方法移动对象(重定位、setLayoutX、Y)以及不同的边界检查(boundsInLocal、BoundsInParent等),但我仍然无法实现这一点。正如您所见,检测仅对一个对象有效,即使有三个对象,也只有一个对象检测碰撞。下面是一些工作代码,演示了该问题: import javafx.application.Application; import

我正在尝试做一些碰撞检测。对于这个测试,我使用简单的矩形
形状
,并检查它们的
边界
,以判断它们是否发生碰撞。虽然检测没有按预期工作。我尝试过使用不同的方法移动对象(重定位、setLayoutX、Y)以及不同的边界检查(boundsInLocal、BoundsInParent等),但我仍然无法实现这一点。正如您所见,检测仅对一个对象有效,即使有三个对象,也只有一个对象检测碰撞。下面是一些工作代码,演示了该问题:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

import java.util.ArrayList;


public class CollisionTester extends Application {


    private ArrayList<Rectangle> rectangleArrayList;

    public static void main(String[] args) {
        launch(args);
    }

    public void start(Stage primaryStage) {
        primaryStage.setTitle("The test");
        Group root = new Group();
        Scene scene = new Scene(root, 400, 400);

        rectangleArrayList = new ArrayList<Rectangle>();
        rectangleArrayList.add(new Rectangle(30.0, 30.0, Color.GREEN));
        rectangleArrayList.add(new Rectangle(30.0, 30.0, Color.RED));
        rectangleArrayList.add(new Rectangle(30.0, 30.0, Color.CYAN));
        for(Rectangle block : rectangleArrayList){
            setDragListeners(block);
        }
        root.getChildren().addAll(rectangleArrayList);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public void setDragListeners(final Rectangle block) {
        final Delta dragDelta = new Delta();

        block.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                // record a delta distance for the drag and drop operation.
                dragDelta.x = block.getTranslateX() - mouseEvent.getSceneX();
                dragDelta.y = block.getTranslateY() - mouseEvent.getSceneY();
                block.setCursor(Cursor.NONE);
            }
        });
        block.setOnMouseReleased(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                block.setCursor(Cursor.HAND);
            }
        });
        block.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {

                block.setTranslateX(mouseEvent.getSceneX() + dragDelta.x);
                block.setTranslateY(mouseEvent.getSceneY() + dragDelta.y);
                checkBounds(block);

            }
        });
    }

    private void checkBounds(Rectangle block) {
        for (Rectangle static_bloc : rectangleArrayList)
            if (static_bloc != block) {
                if (block.getBoundsInParent().intersects(static_bloc.getBoundsInParent())) {
                    block.setFill(Color.BLUE);        //collision
                } else {
                    block.setFill(Color.GREEN);    //no collision
                }
            } else {
                block.setFill(Color.GREEN);    //no collision -same block
            }
    }

    class Delta {
        double x, y;
    }
}
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.scene.Cursor;
导入javafx.scene.Group;
导入javafx.scene.scene;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.paint.Color;
导入javafx.scene.shape.Rectangle;
导入javafx.stage.stage;
导入java.util.ArrayList;
公共类CollisionTester扩展应用程序{
私有ArrayList矩形ArrayList;
公共静态void main(字符串[]args){
发射(args);
}
公共无效开始(阶段primaryStage){
初级阶段。设置标题(“测试”);
组根=新组();
场景=新场景(根,400400);
矩形ArrayList=新ArrayList();
添加(新矩形(30.0,30.0,Color.GREEN));
添加(新矩形(30.0,30.0,Color.RED));
添加(新矩形(30.0,30.0,Color.CYAN));
用于(矩形块:矩形ArrayList){
集光器(块);
}
root.getChildren().addAll(矩形数组列表);
初级阶段。场景(场景);
primaryStage.show();
}
公共空白设置矩形块(最终矩形块){
最终增量dragDelta=新增量();
setOnMousePressed(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent MouseEvent){
//记录拖放操作的增量距离。
dragDelta.x=block.getTranslateX()-mouseEvent.getSceneX();
dragDelta.y=block.getTranslateY()-mouseEvent.getSceneY();
block.setCursor(Cursor.NONE);
}
});
setOnMouseReleased(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent MouseEvent){
block.setCursor(Cursor.HAND);
}
});
setOnMouseDrawed(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent MouseEvent){
setTranslateX(mouseEvent.getSceneX()+dragDelta.x);
block.setTranslateY(mouseEvent.getSceneY()+dragDelta.y);
检查边界(块);
}
});
}
专用无效检查边界(矩形块){
for(矩形静态组:矩形阵列列表)
if(静态组!=块){
if(block.getBoundsInParent()相交(static_bloc.getBoundsInParent()){
block.setFill(Color.BLUE);//冲突
}否则{
block.setFill(Color.GREEN);//无冲突
}
}否则{
block.setFill(Color.GREEN);//无冲突-同一块
}
}
类三角洲{
双x,y;
}
}

您的checkBounds例程中似乎有一个轻微的逻辑错误-您正确地检测到了碰撞(基于边界),但在同一例程中执行后续碰撞检查时覆盖了块的填充

尝试以下操作-它添加了一个标志,以便例程不会“忘记”检测到碰撞:

private void checkBounds(Shape block) {
  boolean collisionDetected = false;
  for (Shape static_bloc : nodes) {
    if (static_bloc != block) {
      static_bloc.setFill(Color.GREEN);

      if (block.getBoundsInParent().intersects(static_bloc.getBoundsInParent())) {
        collisionDetected = true;
      }
    }
  }

  if (collisionDetected) {
    block.setFill(Color.BLUE);
  } else {
    block.setFill(Color.GREEN);
  }
}
请注意,您正在执行的检查(基于父组中的边界)将报告包含同一父组中可见节点边界的矩形的交点

替代实施

如果需要,我更新了原始示例,以便它能够基于节点的可视形状而不是可视形状的边界框进行检查。这使您能够准确检测非矩形形状(如圆)的碰撞。关键是方法


注意:如果有许多形状正在设置动画,则在一个节点内每帧检查一次碰撞将比在任何节点移动时运行碰撞检查更有效(如上面的boundsInParentProperty更改侦听器中所做的).

检查边界例程中似乎有一个轻微的逻辑错误-您正确地检测到了碰撞(基于边界),但在同一例程中执行后续碰撞检查时覆盖了块的填充

尝试以下操作-它添加了一个标志,以便例程不会“忘记”检测到碰撞:

private void checkBounds(Shape block) {
  boolean collisionDetected = false;
  for (Shape static_bloc : nodes) {
    if (static_bloc != block) {
      static_bloc.setFill(Color.GREEN);

      if (block.getBoundsInParent().intersects(static_bloc.getBoundsInParent())) {
        collisionDetected = true;
      }
    }
  }

  if (collisionDetected) {
    block.setFill(Color.BLUE);
  } else {
    block.setFill(Color.GREEN);
  }
}
请注意,您正在执行的检查(基于父组中的边界)将报告包含同一父组中可见节点边界的矩形的交点

替代实施

如果需要,我更新了原始示例,以便它能够基于节点的可视形状而不是可视形状的边界框进行检查。这使您能够准确检测非矩形形状(如圆)的碰撞。关键是方法


注意:如果有许多形状正在设置动画,则在一个节点内每帧检查一次碰撞将比在任何节点移动时运行碰撞检查更有效(如上面的boundsInParentProperty更改侦听器中所做的).

试着用我写的这个来演示JavaFX中各种边界类型的交集关系。好的,我现在感兴趣的似乎都是该文件中的第一个类。我学到的一件重要的事情是检查冲突的changeListener。也可以使用Lay
block.boundsInParentProperty().addListener((observable, oldValue, newValue) -> 
        checkShapeIntersection(block)
);