/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
* Copyright 2008, 2010 Oracle and/or its affiliates. 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 Oracle Corporation 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;
}
}
}