0

Here is my following code:

  public void start(Stage primaryStage) throws Exception {
        Pane root = new Pane();
        Scene scene = new Scene(root, 500, 500, Color.WHITE);

        ImageView image = new ImageView(new Image(getClass().getResourceAsStream("dice.jpeg")));
        image.setX(35);
        image.setY(225);
        image.setFitWidth(50);
        image.setFitHeight(70);
        root.getChildren().add(image);

        Line line = new Line(20, 40, 120, 40);
        line.setStroke(Color.RED);
        line.setStrokeWidth(10);
        root.getChildren().add(line);

        if (line.getBoundsInParent().intersects(image.getBoundsInParent())) {
            System.out.println("intersect");
        }

        Timeline timeline = new Timeline(
                new KeyFrame(
                        Duration.seconds(2),
                        new KeyValue(line.translateYProperty(), 600)
                ));
        timeline.setCycleCount(Animation.INDEFINITE);
        timeline.setAutoReverse(false);

        timeline.play();
        primaryStage.setScene(scene);
        primaryStage.show();
    }

I want this System.out.println("intersect") message to be print when the line and image intersect, but when I run my code it doesn't work. Can anyone please tell me what am I doing wrong? Any help is appreciated!

  • See this question on [collision detection](https://stackoverflow.com/questions/15013913/checking-collision-of-shapes-with-javafx) (maybe this is a duplicate?). Do you really wish to check bounds intersection or do you wish to check visual intersection? When you have animation, you need to check intersection whenever something moves (e.g. in an [AnimationTimer](https://docs.oracle.com/javase/8/javafx/api/javafx/animation/AnimationTimer.html)) rather than when it is created. – jewelsea Sep 13 '17 at 07:37
  • 2
    You could also add a listener to `line.translateYProperty()` and check for collision in it. – ItachiUchiha Sep 13 '17 at 07:49
  • Yes, in this simple case where only the y property is changing, a listener for it will work well and is very straightforward to implement. If your full app is more complicated and multiple properties may be changing each frame, checks within an animation timer might be simpler to manage. – jewelsea Sep 13 '17 at 19:12

1 Answers1

0

I have come up with a solution. This involves using a thread to check all the time while the other code is still running. The error in your code is it only checked once when the animation had not started running.

Obviously, my code is not perfect so you may want to clean it up to suit your needs:

public class Test extends Application{

public static void main(String[] args) {
    Test.launch(args);
    //The thread which checks continues to run so you have to stop it 
    //(There is definitly a better way to do this)
    System.exit(0);
}

@Override
public void start(Stage primaryStage) throws Exception {
    Pane root = new Pane();
    Scene scene = new Scene(root, 500, 500, Color.WHITE);

    ImageView image = new ImageView(new Image(getClass().getResourceAsStream("dice.jpeg")));
    image.setX(35);
    image.setY(225);
    image.setFitWidth(50);
    image.setFitHeight(70);
    root.getChildren().add(image);

    Line line = new Line(20, 40, 120, 40);
    line.setStroke(Color.RED);
    line.setStrokeWidth(10);
    root.getChildren().add(line);

    //new code
    Thread t = new Thread(){
        @Override
        public void run(){
            while(true){               
                try {
                    //you could add a Thread.sleep so it only checks every x miliseconds 
                    Thread.sleep(40);
                    if (line.getBoundsInParent().intersects(image.getBoundsInParent())) {
                        System.out.println("intersect");
                    }
                } catch (InterruptedException ex) {
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        }
    };
    t.start();
    //end of new code

    Timeline timeline = new Timeline(
            new KeyFrame(
                    Duration.seconds(2),
                    new KeyValue(line.translateYProperty(), 600)
            ));
    timeline.setCycleCount(Animation.INDEFINITE);
    timeline.setAutoReverse(false);
    timeline.play();

    primaryStage.setScene(scene);
    primaryStage.show();
}

}
Nyla of Arda
  • 106
  • 3
  • 9
  • You should not query properties of nodes in the active scene graph off of the JavaFX application thread (it will cause [race conditions](https://en.wikipedia.org/wiki/Race_condition#Software)). The intersects check should be performed in a [Platform.runLater call](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Platform.html). Or, better yet, the custom thread should be replaced with an [AnimationTimer](https://docs.oracle.com/javase/8/javafx/api/javafx/animation/AnimationTimer.html) and the check should be done within the timer's `handle()` method. – jewelsea Sep 13 '17 at 19:06