Macca Blog

My life experiences with code and design

Quick Tip for JavaFX and the contains() method

Posted on by Mark

After the release of JavaFX, I have been just getting my existing games up-to-date to use the 1.0 SDK. So far, and I will blog on this later on, it has been pain free. But there was one thing that I noticed, and that was my collision detection timelines were not working anymore.

The Node contains() method (in the preview SDK) took into account the transformations that have been applied.

For example, if you have a Rectangle at x=0 and y=0 and a width of 15 and a height of 10, then apply x/y transformations of 10 each.

Before:
The start X is: 0
The end X is: 15
The start Y is: 0
The end Y is: 10

After:
The start X is now: 10
The end X is now: 25
The start Y is now: 10
The end Y is now: 20

The call to .contains(x, y) (in the preview SDK, where x=17 and y=12) would return true.

However, this exact same situation did not return true for the 1.0 SDK.

Infact, the 1.0 SDK introduced a whole new set of properties and methods that are really very useful and will help you out in a lot of different situations.

There is a read-only property called boundsInScene (as well as many others) on the Node object that will give you the bound of the node in the current scene as a 2D Rectangle data type.

The reason why the contains() method in the 1.0 SDK did not return true above, is because it does not appear to take into account the x and y transformations. However, the boundsInScene property does.

So you can do this:

node.boundsInScene.contains(x, y);

Which then, as you would expect, tests if the bounds of the node within the scene, after transformation, contains the x and y coordinates. And it does.

Below is some example source code that you can play with to see what exactly happens:

package coordinatessample;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.Color;
import javafx.scene.input.MouseEvent;
import javafx.animation.Timeline;
import javafx.animation.KeyFrame;

/**
* @author Mark Macumber
*/
var xtrans = 0.0;

var rec = Rectangle {
x: 10, y: 100,
width: 140, height: 90
stroke: Color.BLACK
fill: Color.WHITE
translateX: bind xtrans;
};

Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: [
KeyFrame {
time: 50ms
action: function(){ xtrans += 1; }
}
]
}.play();

Stage {
title: "Bounds Testing Sample"
width: 500
height: 500
scene: Scene {
content: [
Rectangle {
x: 0,
y: 0
width: 500,
height: 500
fill: Color.WHITE

onMouseClicked: function( e: MouseEvent ):Void {
if (rec.contains(e.x, e.y)){
println("over contains()");
}
if (rec.boundsInScene.contains(e.x, e.y)){
println("over boundsInScene.contains()");
}
}
},
rec
]
}
}

Basically, it just moves a rectangle across the screen in the positive X direction. Then, when you click on the shape as its moving you can see the result of the different contains() approaches.

I hope this helps shed some light on the basics of FX Script, and there will be more as I learn more too!

I am currently in the process of updating my SpaceshipFX game to use the 1.0 SDK, and I will report back when its all done.

I love feedback and advice too, I surely understand that there are many new things to learn with FX script and that the advice I have given may be described in different ways. So please give me some feedback if you want to!

This entry was posted in JavaFX. Bookmark the permalink.

Leave a Comment

Your email address will not be published. Required fields are marked *


*