Ball.java


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