1

Just as a preface, I am very new to programming in JavaFX. (We had an introduction to JavaFX in one of my classes last semester, and for the last month or so I've been working on making a simple game in JavaFX.)

An issue I've run into is trying to detect the collision of a Pane within one StackPane with the Pane inside another StackPane. Specifically, I have a "Player" node in the Game class ("Player" extends abstract "Sprite" which extends StackPane) along with some "Asset" nodes ("Asset" being an abstract parent class that like "Sprite" also extends StackPane). Both "Player" and every "Asset" node are comprised of an ImageView and Pane objects that are to be the "boundaries" of the node.

Here's how I'm attempting to track collisions in the Game class, but it's not working:

protected void update() {
    // Call playerBoundsHandler in update cycle
    for (Asset asset : this.gameArea.getAssets()) {
        playerBoundsHandler(asset);
    } // for
} // update

private void playerBoundsHandler(Asset asset) {
    for (Pane boundary : asset.getAssetBoundaries()) {
        if (player.getPlayerStandingAreaBox()
        .getBoundsInParent()
        .intersects(boundary.getBoundsInParent())) {
            // do stuff here
        } // if
    } // for
} // playerBoundsHandler

I'm guessing there's something wrong with using getBoundsInParent() here since I'm trying to track the intersection of child nodes within two separate nodes, but I have no idea what the solution is. Is there something I need to do with getBoundsInLocal or some other method?

Here's the relevant part of the Player class for clarification's sake:

/** 
* Player class constructor. 
* Player class extends "Sprite" (abstract class)
* which extends StackPane.
*/
public Player(double xSpawn, double ySpawn) {
    // Add Player Standing Box (a Pane situated at the feet of the Player sprite)  
    this.playerStandingAreaBox = new Pane();
    // width, height, etc. set here
    this.getChildren().add(playerStandingAreaBox);
    this.setAlignment(playerStandingAreaBox, Pos.BOTTOM_CENTER);
} // Player constructor

public Pane getPlayerStandingAreaBox() {
    return this.playerStandingAreaBox;
} // getPlayerStandingAreaBox

The Asset child classes follow a design almost identical to the Player class here. In case it's also needed for clarification, here's the "Highway" class:

public class Highway extends Asset {

    public Highway(double translateX, double translateY) {
        // call super here
        setAssetBoundaries();
    } // Highway constructor

    @Override
    setAssetBoundaries() {
        Pane boundaryOne = new Pane();
        // set boundaryOne settings
        this.getChildren().add(boundaryOne);
        this.assetBoundaries.add(boundaryOne);
        Pane boundaryTwo = new Pane();
        // set boundaryTwo settings
        this.getChildren().add(boundaryTwo);
        this.assetBoundaries.add(boundaryTwo);
    } // setAssetBoundaries
 
    /**
    * assetBoundaries is an ArrayList<Asset> object also inherited.
    * getAssetBoundaries() is inherited from the "Asset" class
    * which returns assetBoundaries.
    */

The screenshot below shows my Player sprite (don't judge the awful pixel art! I already know the guy's right arm looks janky and the rifle looks ridiculous!) with his standing box highlighted in red, and the boundaries of a "Highway" Asset highlighted in yellow at both the very top and very bottom. I want to register when the Player's box intersects one of the boxes of the Highway.

Player and Highway

John
  • 41
  • 4
  • I didn't read all of your question, but you may find related info in: [Checking Collision of Shapes with JavaFX](https://stackoverflow.com/questions/15013913/checking-collision-of-shapes-with-javafx). My guess is that to get a more targeted answer you may need ask the question in a different way, by providing a [mcve] (complete, minimal code, that can be copied and pasted to run, but not the entire app, and written to demonstrate just the collision issue with two shapes and nothing else). – jewelsea Jun 04 '21 at 18:55
  • 3
    If they have different parents, comparing the bounds in the parent will not work (you are looking at different coordinate systems for each). You need to compare their bounds in a coordinate system common to both of them, e.g. the scene. So, e.g. `player.localToScene(player.getBoundsInLocal())` and `boundary.localToScene(boundary.getBoundsInLocal())`. – James_D Jun 04 '21 at 18:58
  • Thank you James_D! Since I posted the question, I've been following that trail but haven't figured out how to set it up exactly. I've got it to do exactly what I want to do now using what you gave! @jewelsea Sorry about that. I'll keep in mind MRE next time I ask a question on here. – John Jun 04 '21 at 19:10
  • 2
    I wrote a [demo for understanding layout bounds](https://gist.github.com/jewelsea/1441960) which might help you to understand what is happening. It is an older demo written when JavaFX 2 was first released, so it may not work out of the box with the latest JavaFX versions. – jewelsea Jun 04 '21 at 19:28

1 Answers1

3

Thanks, James_D. The following change does exactly what I want it to do.

private void playerBoundsHandler(Asset asset) {
    for (Pane boundary : asset.getAssetBoundaries()) {
        Bounds boundaryBoundsInScene = boundary.localToScene(boundary.getBoundsInLocal());
        Bounds playerStandingBoxBoundsInScene = player.getPlayerStandingBoxArea()
            .localToScene(player.getPlayerStandingBoxArea().getBoundsInLocal());
        if (boundaryBoundsInScene.intersects(playerStandingBoundsInScene)) {
            // do stuff here
        } // if
    } // for
} // playerBoundsHandler
John
  • 41
  • 4