import java.awt.Graphics; import java.awt.Color; /**Defines a circular ball(implements interface circle) that has a name, color, mass, velocity, radius, x, and y coordinates.*/ public class Ball extends MoveableObject implements Circle { private double x_location; private double y_location; private double radius; private boolean willCollideWithWallThisTimeStep = false; private boolean willCollideWithBallThisTimeStep = false; private Ball collidingBallObject; private StationaryObject collidingStationaryObject; private MyMathOperations operation; public Ball() //default constructor { super(); x_location = 0; y_location = 0; radius = 0; operation = new MyMathOperations(); } /**Creates a ball. The coordinates are at the center of the circular ball. * @param (name, color, mass, velocity) * @param x x-coordinate * @param y y-coordinate*/ public Ball(String name, Color color, double mass, double xVelocity, double yVelocity, double x, double y, double r) { super(name, color, mass, xVelocity, yVelocity); setCoordinates(x, y, radius); } public void setCoordinates(double newX_location, double newY_location, double newRadius) { x_location = (newX_location); y_location = (newY_location); radius = newRadius; } public void setCoordinates(double newX_location, double newY_location) { x_location = (newX_location); y_location = (newY_location); } public void setRadius(double newRadius) { radius = newRadius; } public double getXCoordinate() { return x_location; } public double getYCoordinate() { return y_location; } public double getRadius() { return radius; } public void updatePosition(double dt)//velocity must be constant { //dt = operation.truncate(dt); //x_location = operation.truncate(x_location + (super.getXVelocity())*dt); x_location = (x_location + (super.getXVelocity())*dt); //y_location = operation.truncate(y_location + (super.getYVelocity())*dt); y_location = (y_location + (super.getYVelocity())*dt); } public double timeToCollision(Ball that) { if (this == that) return 1.0/0.0; double dx = that.getXCoordinate() - this.getXCoordinate(), dy = that.getYCoordinate() - this.getYCoordinate(); double dvx = that.getXVelocity() - this.getXVelocity(); double dvy = that.getYVelocity() - this.getYVelocity(); double dvdr = dx*dvx + dy*dvy; if(dvdr >= 0) return 1.0/0.0; double dvdv = dvx*dvx + dvy*dvy; if(dvdv == 0) return 1.0/0.0; double drdr = dx*dx + dy*dy; double sigma = this.getRadius() + that.getRadius(); double d = (dvdr*dvdr) - dvdv * (drdr - sigma*sigma); if (d < 0) return 1.0/0.0; return -(dvdr + Math.sqrt(d)) / dvdv; } public void bounce(Ball that) { //double energy = (0.5*(this.getMass()*(Math.pow(this.getXVelocity(), 2) + Math.pow(this.getYVelocity(), 2)) //+ that.getMass()*(Math.pow(that.getXVelocity(), 2) + Math.pow(that.getYVelocity(), 2)))); //System.out.println("Energy = " + energy); double dx = that.getXCoordinate() - this.getXCoordinate(), dy = that.getYCoordinate() - this.getYCoordinate(); double dvx = that.getXVelocity() - this.getXVelocity(); double dvy = that.getYVelocity() - this.getYVelocity(); double dvdr = dx*dvx + dy*dvy; double dist = this.getRadius() + that.getRadius(); double J = (2 * this.getMass() * that.getMass() * dvdr) / ((this.getMass() + that.getMass()) * dist); //double J = (2 * this.getMass() * dvdr) / (((this.getMass()/that.getMass()) + 1.0) * dist); double Jx = (J * dx) / dist; double Jy = (J * dy) / dist; //this.setVelocity(operation.truncate(this.getXVelocity() + (Jx / (this.getMass()))), operation.truncate(this.getYVelocity() + (Jy / (this.getMass())))); this.setVelocity((this.getXVelocity() + (Jx / (this.getMass()))), (this.getYVelocity() + (Jy / (this.getMass())))); //that.setVelocity(operation.truncate(that.getXVelocity() - (Jx / (that.getMass()))), operation.truncate(that.getYVelocity() - (Jy / (that.getMass())))); that.setVelocity((that.getXVelocity() - (Jx / (that.getMass()))), (that.getYVelocity() - (Jy / (that.getMass())))); //energy = (0.5*(this.getMass()*(Math.pow(this.getXVelocity(), 2) + Math.pow(this.getYVelocity(), 2)) //+ that.getMass()*(Math.pow(that.getXVelocity(), 2) + Math.pow(that.getYVelocity(), 2)))); //System.out.println("energy after = " + energy); } public double ballEnergy() { double energy = (0.5*(this.getMass()*(Math.pow(this.getXVelocity(), 2)))) + (0.5*(this.getMass()*(Math.pow(this.getYVelocity(), 2)))); return energy; } public void bounce(StationaryObject that) { double u1x = this.getXVelocity(); double u1y = this.getYVelocity(); double m1 = this.getMass(); double m2 = that.getMass(); double u2x = that.getXVelocity(); double u2y = that.getYVelocity(); double v1x = (u1x*(m1 - m2) + 2*m2*u2x) / (m1 + m2); double v2x = (u2x*(m2 - m1) + 2*m1*u1x) / (m1 + m2); double v1y = (u1y*(m1 - m2) + 2*m2*u2y) / (m1 + m2); double v2y = (u2y*(m1 - m2) + 2*m2*u1y) / (m1 + m2); this.setVelocity(v1x, v1y); //System.out.println(v1x + ", " + v1y); //there is no set method for the stationary object because the stationary object does not change velocity. } public void setWillCollideWithWallThisTimeStep(boolean expression) { willCollideWithWallThisTimeStep = expression; } public boolean getCollisionWallAnswer() { return willCollideWithWallThisTimeStep; } public void setWillCollideWithBallThisTimeStep(boolean expression) { willCollideWithBallThisTimeStep = expression; } public boolean getCollisionBallAnswer() { return willCollideWithBallThisTimeStep; } public void setCollidingBallObject(Ball that) { collidingBallObject = that; } public void setCollidingStationaryObject(StationaryObject that) { collidingStationaryObject = that; } public Ball getCollidingBallObject() { return collidingBallObject; } public StationaryObject getCollidingStationaryObject() { return collidingStationaryObject; } /**Draws the ball onto the canvas at x coordinate - radius, and y coordinate - radius. * The coordinates defined the center of the circle, but the Graphics paint method inscribes the circle in a square, * and defines the upper left corner as the coordinates.*/ public void draw(Graphics canvas) { canvas.setColor(super.getColor()); //System.out.println("I'm in Ball.draw" + x_location + "\t" + y_location + (getColor()).toString()); canvas.fillOval(((int)x_location) - (int)radius, ((int)y_location) - (int)radius, 2*(int)radius, 2*(int)radius); } }