As promised, the source code for the Laser Orbit demo is now available as a NetBeans (ANT) project under the MIT license. I refined the source since I originally wrote the demo, as I’ve learned more about JavaFX writing other demos (coming soon). As a result I’ve cut the code down by a third and I’m left with something that is almost entirely declarative.

def FPS = 24;
def SPRINGNESS = 0.2;
def DECAY = 0.8;
def SPAN_DISTANCE = 100;

var current = Point {}
var mouse = Point {x:225 y:200}
var previous = Point {}
var target = Point {}
var temp = Point{}
var random = new Random();
var scene: Scene;

Stage {
title: "Laser Orbit"
width: 550
height: 400
scene: scene = Scene {
content: [
Rectangle {
x: 0
y: 0
width: bind scene.width
height: bind scene.height
fill: Color.BLACK
onMouseMoved: function(event: MouseEvent) {
mouse.x = event.x;
mouse.y = event.y;
}
}
]
}
}

class Point {
var x = 0.0;
var y = 0.0;
}

Timeline {
keyFrames: [
KeyFrame {
time: 1000ms / FPS
action: function() {
previous.x = current.x;
previous.y = current.y;
target.x = mouse.x + (SPAN_DISTANCE - SPAN_DISTANCE * 2 * random.nextDouble());
target.y = mouse.y + (SPAN_DISTANCE - SPAN_DISTANCE * 2 * random.nextDouble());
temp.x = temp.x * DECAY + (target.x - current.x) * SPRINGNESS;
temp.y = temp.y * DECAY + (target.y - current.y) * SPRINGNESS;
current.x = current.x + temp.x;
current.y = current.y + temp.y;
var line = Line {
startX: previous.x
startY: previous.y
endX: current.x
endY: current.y
strokeWidth: 1.5
stroke: Color.BLUE
}
insert line into scene.content;
Timeline {
keyFrames: [
KeyFrame {
time: 0.0s
values: {line.opacity => 1.0}
},
KeyFrame {
time: 1.0s
values: {line.opacity => 0.0 tween Interpolator.LINEAR}
action: function() {
delete line from scene.content;
}
}
]
}.play();
}
}
]
repeatCount: Timeline.INDEFINITE
}.play();

Download the NetBeans project.