Ball.java
import javafx.geometry.*; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; import java.util.Random; public class Ball { Circle circle = new Circle(); double px, py; double vx, vy; double mass; double radius; Color color; String name; static int count = 0; Ball() { color = Color.rgb(255,180,0); vx = 8; vy = 9; name = "default"; set_radius(17); setPosition(50,60); circle.setFill(color); } Ball(double px, double py, double vx, double vy, Color color) { this.vx = vx; this.vy = vy; this.color = color; name = "ball" + (++count); set_radius(17); setPosition(px,py); circle.setFill(color); } Ball(int px, int py) { this.px = px; this.py = py; vx = vy = 0.0; color = Color.BLACK; set_radius(1); } public void randomize(double v, double wd, double ht) { Random r = new Random(); double x = wd*r.nextDouble(); double y = ht*r.nextDouble(); setPosition(x,y); double theta = r.nextDouble()*2.0*Math.PI; vx = v*Math.cos(theta); vy = v*Math.sin(theta); } public void set_name(String name) { this.name = name; } public void set_radius(double r) { radius = r; mass = r*r; circle.setRadius(radius); } public void setColor(Color c) { color = c; circle.setFill(color); } public void setPosition(double x, double y) { px = x; py = y; circle.setCenterX(px); circle.setCenterY(py); } public String toString() { if (name!=null) return String.format(" %s (%.1f, %.1f)",name,px,py); else return String.format(" pos (%.1f, %.1f) ",px,py); } public String info() { return String.format(" %s pos (%.1f, %.1f) vel (%.1f %.1f) ",name,px,py,vx,vy); } public void move(double delta) { px += vx*delta; py += vy*delta; circle.setCenterX(px); circle.setCenterY(py); } public boolean contains(Point2D pt) { double dist = Math.hypot(pt.getX()-px,pt.getY()-py); return (dist<radius); } public double dist(Ball b) { // relative position double dx = b.px - px; double dy = b.py - py; double dist = Math.hypot(dx,dy); // test radius double r = radius + b.radius; return dist-r; } public double intersect(Ball b) { double tx = 1000.0; double epsilon = -1e-6; // relative velocity double rx = b.vx - vx; double ry = b.vy - vy; // relative position double dx = b.px - px; double dy = b.py - py; // test radius double r = radius + b.radius - 1; double A = rx*rx+ry*ry; double B = rx*dx+ry*dy; double C = dx*dx + dy*dy - r*r; if (B>0.0) return tx; // balls moving apart if (C<epsilon) System.out.println("already intersecting " + this + " " + b + " C " + C); if (C<epsilon) return -1.0; // already intersecting if (A<=0.0) return tx; // no relative velocity // quadratic At^2 + 2Bt + C = 0 double radical = B*B-A*C; if (radical<0.0) return tx; // no intersection (balls miss) double R = Math.sqrt(radical); double t; if (B>0) t = (-B + R)/A; else t = -(B+R)/A; if (t<0.0) return tx; // no intersection in future return t; } public double intersect_window_vertical(double width) { if (vx<0) { return (px-radius)/(-vx); } else if (vx>0) { return (width - px - radius)/(vx); } return -1.0; } public double intersect_window_horizontal(double height) { if (vy<0) { return (py-radius)/(-vy); } else if (vy>0) { return (height - py - radius)/vy; } return -1.0; } }
Maintained by John Loomis, updated Sat Mar 03 12:45:57 2018