/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
* Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
*
* This file is available and licensed under the following license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Sun Microsystems nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import javafx.scene.Cursor;
import javafx.scene.CustomNode;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Circle;
public class Ball extends CustomNode {
public-init var sign: Boolean;
public-init var radius: Number;
var vx: Number;
var vy: Number;
var event: MouseEvent on replace old {
if (event != null) {
vx = event.dragX - old.dragX;
vy = event.dragY - old.dragY;
translateX += vx;
translateY += vy;
}
}
override function create() {
def color = if (sign) then Color.RED else Color.BLUE;
Circle {
radius: radius - 1
stroke: color
fill: RadialGradient {
radius: radius
focusX: radius * 0.8
focusY: radius * -0.8
proportional: false
stops: [
Stop {offset: 0 color: Color.WHITE},
Stop {offset: 1 color: color}
]
}
cursor: Cursor.HAND
onMouseDragged: function(event) {
this.event = event;
}
onMouseReleased: function(event) {
this.event = null;
}
}
}
public function update() {
if (event == null) {
translateX += (vx *= 0.9);
translateY += (vy *= 0.9);
if (translateX < radius) { vx = -vx; translateX = radius + radius - translateX }
if (translateY < radius) { vy = -vy; translateY = radius + radius - translateY }
var w = scene.width - radius;
var h = scene.height - radius;
if (translateX > w) { vx = -vx; translateX = w + w - translateX }
if (translateY > h) { vy = -vy; translateY = h + h - translateY }
}
}
public function process(ball: Ball) {
var d = ball.radius + radius;
var dx = ball.translateX - translateX;
var dy = ball.translateY - translateY;
var dd = (dx * dx) + (dy * dy);
var collision = dd <= (d * d);
if (collision) {
var dvx = ball.vx - vx;
var dvy = ball.vy - vy;
var mag = dvx * dx + dvy * dy;
if (mag <= 0) {
mag /= dd;
var delta_vx = dx * mag;
var delta_vy = dy * mag;
ball.vx -= delta_vx * radius / d;
ball.vy -= delta_vy * radius / d;
vx += delta_vx * ball.radius / d;
vy += delta_vy * ball.radius / d;
}
}
if (dd > 0) {
var f = 0.05 * ball.radius * radius / dd;
var delta_vx = dx * f;
var delta_vy = dy * f;
if (collision or (ball.sign == sign)) {
delta_vx = -delta_vx;
delta_vy = -delta_vy;
}
ball.vx -= delta_vx * radius / d;
ball.vy -= delta_vy * radius / d;
vx += delta_vx * ball.radius / d;
vy += delta_vy * ball.radius / d;
}
}
}