
Tons of Bouncy Balls
Introduction
In the second installment of the series “JavaFX to JavaScript and Back” we will look at code! If you remember what we discussed in my previous post of Part 1 showing a demo of many bouncy balls. If you want to skip to the source code go to demo and click on download project.
Newcomers
If you are new and just getting started with JavaFX I strongly suggest JavaFX.com or Java.sun.com. If you are like me, one who knows enough to be dangerous please skip to Getting Started. Newcomers should take a look at books in the References section at the end of this article. Another awesome resource is the “Free” 15-Week JavaFX Programming (with Passion!) Online Course w/ Sang Shin & James Weaver.
Assumptions
- NetBeans 6.5.1 is installed with JavaFX 1.2 pluggin.
- Java SDK 1.6 update 14
- Know basic JavaScript
- Know basic HTML
Getting started
To give you a quick recap of the scenarios:
- Create Bouncy Balls (JavaScript to JavaFX)
- Remove Bouncy Balls (JavaFX to JavaScript)
Create a JavaFX Applet
Step 1: Create a Ball (Custom Node)
First create a class called Ball that extends a CustomNode. The key is overriding the create() method of the CustomNode class. We first create a Circle with a RadialGradient fill. Next we create a Group containing the circle in its content attribute. Then add the onMousePressed function to the group to detect a mouse pressed event which will remove this ball’s instance from the Scene (Game Area) and decrements the numBalls variable which updates the Web Page’s form element Number of Balls. Finally we return the group (ball variable).
class Ball extends CustomNode {
public var velocity:Velocity;
public var centerX:Integer=100;
public var centerY:Integer=100;
public var radius:Integer;
public var fill:Color;
protected override function create(): Node {
var circle:Circle = Circle {
centerX: centerX, centerY: centerY
radius: radius
fill: RadialGradient {
centerX: centerX - radius / 3
centerY: centerY - radius / 3
radius: radius
proportional: false
stops: [
Stop {
offset: 0.0
color: getRndColor()
},
Stop {
offset: 1.0
color: Color.BLACK
}
] // stops
} // RadialGradient
} // circle
var ball = Group{
content:[circle];
// remove ball
onMousePressed: function( e: MouseEvent ):Void {
delete this from gameArea;
numBalls--;
}
} // Group
return ball;
} // create()
} // Ball
Step 2: Create initial ball to be put in Scene
You should notice I’ve created a few script level functions which conveniently return random values to create a Ball node. I won’t list those function for brevity. The random generated attributes are: velocity, centerX, centerY, radius, circle.fill = (RadialGradient 1st stop Color [Step 1 – Line 19])
// create an initial ball to float around.
var initialBallRadius = getRndRadius();
var rndCenter:Point = getRndCenter(500, 400, initialBallRadius);
var firstBall = Ball{
velocity:getRndVelocity()
centerX: rndCenter.x
centerY: rndCenter.y
radius: initialBallRadius
};
Step 3: Create the Scene to display Balls
The variable gameArea is a sequence of Nodes. You will notice the ball instance from Step 2 is the first node in the sequence. The scene’s content attribute is bound to the gameArea variable. During run time as nodes are added and removed from the game area the scene will dynamically update the visible nodes.
var gameArea:Node[] = [firstBall, toggleAnimationButton, mainRectRegion];
var scene:Scene = Scene {
content: bind gameArea
fill:Color.TRANSPARENT
};
Step 4: Create the Stage
This is the top level container which holds the scene.
Stage {
title: "Application title"
width: 500
height: 400
opacity: bind mainScreenOpacity;
scene: scene
}
Step 5: Create a game or animation loop using the Timeline class
Here we create a Timeline instance that will run indefinitely (Timeline.INDEFINITE) with a single key frame (KeyFrame) which periodically updates each bouncy ball’s attributes which eventually renders each ball node with a new x and y position based on the velocity. Also the Timeline (gameLoop) is started immediately using the play() function.
var gameLoop:Timeline = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time: 1s / 50
canSkip : true
action: function() {
for (node:Node in gameArea) {
if (not (node instanceof Ball)){
continue; // don't update non balls
}
var ball = node as Ball;
var xMin = ball.boundsInParent.minX;
var yMin = ball.boundsInParent.minY;
var xMax = ball.boundsInParent.maxX;
var yMax = ball.boundsInParent.maxY;
// Collision - boundaries
if (xMin scene.width){
ball.velocity.xVelocity = ball.velocity.xVelocity * -1;
}
if (yMin scene.height){
ball.velocity.yVelocity = ball.velocity.yVelocity * -1;
}
ball.translateX = ball.translateX + ball.velocity.xVelocity;
ball.translateY = ball.translateY + ball.velocity.yVelocity;
}
} // action
} //
]
};
gameLoop.play();
Step 6: Create the AppletStageExtension
This is the reference to the JavaFX applet which would assist with browser functionality such as the evaluation of JavaScript code.
var applet: AppletStageExtension;
Step 7: Create the numBalls variable keeping track of adds and removes.
The numBalls variable has a trigger (on replace) that updates the HTML page’s input text field “numBalls“. You should notice the id attribute of the tag is name “numBalls“. An id is a way to uniquely locate the form element in the HTML DOM (in this case a reference to the input field. When numBalls variable changes the trigger will evaluate the JavaScript code “document.getElementById(‘numBalls’).value = {numBalls}”. What this does is populate the form element field’s ‘id’ called “numBalls” whenever the JavaFX variable numBalls is updated.
var numBalls:Integer = 1 on replace {
applet.eval("document.getElementById('numBalls').value = {numBalls}");
};
Step 8: Create a JavaFX function to add lots of balls
The HTML Web page will have a JavaScript function that would call the JavaFX function below when the user presses the Add Ball(s) button.
You will notice the FX.deferAction() call, which ensures updates to JavaFX classes are happening on the JavaFX main processing thread. This function will instantiate num balls inserts into the game area (Scene content) and increments the numBalls (trigger will update Web page’s form element).
// This function is called from the JavaScript button and numBallsToAdd field
function addBalls(num:Integer) : Void {
FX.deferAction(function() : Void {
for( i in [1..num]){
var curBallRadius = getRndRadius();
var rndCenter:Point = getRndCenter(500, 400, curBallRadius);
var b = Ball{
velocity:getRndVelocity()
centerX: rndCenter.x
centerY: rndCenter.y
radius: curBallRadius
fill: getRndColor()
};
insert b into gameArea;
numBalls++;
}
});
}
Create a HTML Web page containing the JavaFX applet
Step 9: Create HTML Web page to display JavaFX applet

Run in Browser
After creating the project in NetBeans select project / properties / Run (categories) / Application Execution Model – Run in Browser.
Step 10: Build Project
Building the project which will create files in the {PROJECT_HOME}/dist directory.
Step 11: Copy originally NetBeans created HTML file of the dist directory to another name
Use the copied and renamed HTML file and not the original because when the build process occurs it will overwrite the original HTML generated file.
Step 12: Modify HTML code to contain JavaScript to call JavaFX applet.
javafx(
{
archive: "JavaFXtoJavaScript.jar",
draggable: true,
width: 500,
height: 400,
code: "javafxtojavascript.Main",
name: "JavaFXtoJavaScript",
id: "ballApp"
},
{ isApplet: "true" }
);
function addBalls() {
document.ballApp.script.addBalls(document.getElementById('numBallsToAdd').value);
}
Step 13: Modify HTML to contain Form Elements.
<form>
<table>
<tr><th>Add balls to Scene :</th>
<td><input id=”numBallsToAdd” name=”numBallsToAdd” value=”1″/></td>
<td><input onClick=”addBalls();” type=”button” name=”addButton” value=”Add Ball(s)”/></td>
</tr>
<tr>
<th>Number of balls: </th>
<td><input id=”numBalls” name=”numBalls” READONLY/></td>
</tr>
</table>
<br/>
</form>
Running Applet in Browser through NetBeans
Step 14: Run application or hit F6 key
This will launch the JavaFX applet into the browser from the original HTML page created from the build. Go to the address and modify the URL (Just the file name) to use the modified copy which would run the JavaFX applet along with the form elements added from step 12 – 13.
Conclusion
Although the example only used simple attributes of the AppletStageExtension there are other properties and events to explore such as onAppletRestored, showDocument(), etc. Hopefully we can get away from HTML and just have rich client applications, however I don’t think the browser is going away anytime soon. So we can happily go from JavaFX to JavaScript and Back!
Enjoy. Let me know what you think.
References:
Pro JavaFX Platform by Jim Weaver, Weiqi Gao, Stephen Chin, and Dean Iverson
JavaFX: Developing Rich Internet Applications by Jim Clarke, Jim Connors and Eric J. Bruno
Essential JavaFX by Gail Anderson and Paul Anderson