/**
 * An instance of this class is a turtle object that is a ball
 * with the methods that enable it to move with predefined velocities
 * 
 * Written By: Joe Vulih and Jon Rosales
 * 
 * Execute this to see the ball with flames coming out
 * of it as it moves:
 * 
 *    b= new Balljdr59jpv23(30, 40, 30);
      b.inMotionFlames();
 */

import java.awt.*;

public class Balljdr59jpv23 extends Turtle {
  private int radius; //the radius of the ball
  private int vx; //the x velocity of the ball
  private int vy; //the y velocity of the ball
  
  /**
   * A constructor that initializes the fields of the Ball object, x velocity newvx,
   * y velocity newvy and radius r, and centers the
   * ball at position (x,y) and sets the color to c.
   */
  public Balljdr59jpv23(int x, int y, int newvx, int newvy, int r, Color c) {
    radius= r;
    vx= newvx;
    vy= newvy;
    moveTo(x, y, 0);
    setColor(c);
    fillCircle(2*r);
  }
  
  /**
   * A constructor that initializes the fields of a Ball object, x velocity newvx,
   * y velocity newvy, and radius r
   */
  public Balljdr59jpv23(int newvx, int newvy, int r){
    radius= r;
    vx= newvx;
    vy= newvy;
    moveTo(getWidth()/2, getHeight()/2, 0);
    setColor(Color.black);
    fillCircle(2*r);
  }
  
  /**
   * A method that moves the ball once, taking into account if the ball is about to hit a wall
   * and also taking into account the distance the ball if from the wall so it does not simply 
   * reverse direction where it is but takes into account the distance it needs to travel between
   * its position and the wall before it gets reflected back
   */
  public void moveBallOnce() {
    eraseBall(); //erase the ball from its current position
    int distanceX= 0; //the ball's distance from the wall on the x axis, used if the ball will hit the wall
    int distanceY= 0; //the ball's distance from the wall on the y axis, used if the ball will hit the wall
    
    //A series of conditions that see if the ball is going to hit the wall and finds the distance of the edge of the ball to the wall
    //and assigns that value to either distanceX or distanceY depending on if it will hit a ball on the x axis or y axis
    if((getX()+radius+vx)>getWidth()){
      distanceX= -(getWidth() - getX() - radius);
      vx= -vx;
    }
    else if((getX()-radius+vx)<0) {
      distanceX= (getX() - radius);
      vx= -vx;
    }
    if(((getY()+radius+vy)>getHeight())){
      distanceY= -(getHeight() - getY() - radius);
      vy= -vy;
    }
    else if((getY()-radius+vy)<0){
      distanceY= (getY() - radius);
      vy= -vy;
    }
    
    //moves the ball given the velocity, its position, and any displacement it needs to make to correct for the position of the wall
      moveTo((getX()+vx-2*distanceX),(getY()+vy-2*distanceY), 0);
    
    //Redraw the ball
    fillCircle(2*radius);
  }
  
  /**
   * A method that sets the ball in motion perpetually
   */
  public void inMotion() {
    while(true) {
      pause(100);
      moveBallOnce();
    }
  }
  
  /**
   * A method that sets two balls in motion together perpetually
   */
  public static void inMotion(Balljdr59jpv23 b1, Balljdr59jpv23 b2) {
    while(true) {
      b1.pause(100);
      b1.moveBallOnce();
      b2.moveBallOnce();
    }
  }
  
  /**
   * A method to erase the ball at its current position, and then change the
   * pen color back to what it was.
   */
  public void eraseBall() {
    Color save= getColor();
    setColor(Color.white);
    fillCircle(2*radius);
    setColor(save);
  }
  
  /**
   * A method that puts the ball in motion with a tail that looks like flames
   */
  public void inMotionFlames() {
    // the balls that are the flames of the tail
    Balljdr59jpv23 red= new Balljdr59jpv23(this.getX()-vx, this.getY()-vy, vx, vy, radius, Color.red);
    Balljdr59jpv23 orange= new Balljdr59jpv23(this.getX()-3*vx/2, this.getY()-3*vy/2, vx, vy, radius, Color.orange);
    Balljdr59jpv23 yellow= new Balljdr59jpv23(this.getX()-2*vx, this.getY()-2*vy, vx, vy, radius, Color.yellow);
    
    // the loop that keeps the balls in motion
    while(true) {
      this.pause(100);
      this.moveBallOnce();
      red.moveBallOnce();
      orange.moveBallOnce();
      yellow.moveBallOnce();
    }
  }
}