
/*
   An object belonging to the BouncingBall class  is a colored circle that
   is meant to be used with SimpleAnimationApplet.java.  The ball is created
   with a specified color, position, and radius.  At the time it is created,
   a random velocity is chosen for it.  The doFrame() method draws the
   ball and changes its position by adding the velocity to the current
   position.  A setPosition() method is provided for changing the position.
   The headTowards() method changes the velocity so that the ball is moving
   in the direction of a specified point.
   
   David Eck, 10 October 1998
*/

import java.awt.*;

public class BouncingBall {

   private Color color;  // The ball's color; does not change after ball is created.
   private int radius;   // The radius of the ball; does not change.
   private double centerX, centerY;      // The position of the ball's center.
   private double velocityX, velocityY;  // The ball's velocity, given in terms of
                                         //   the amount by which centerX and centerY
                                         //   change in each frame.


   public BouncingBall(Color color, int centerX, int centerY, int radius) {
         // Constructor.  Construct a new bouncing ball object with the specified
         // color, position, and radius.  The x and y components of the velocity
         // are random numbers between -10 and 10, except that at least of of
         // components must be greater than 3 in absolute value.
      this.color = color;
      this.centerX = centerX;
      this.centerY = centerY;
      this.radius = radius;
      do {
         velocityX = (int)(20*Math.random() - 10);
         velocityY = (int)(20*Math.random() - 10);
      } while (Math.abs(velocityY) <= 3 && Math.abs(velocityX) <= 3);
   }
   

   public void doFrame(Graphics g, int width, int height) {
         // Draw the ball in the given graphics context, g.  Then adjust the
         // position of the ball by adding the velocity to the current position.
         // Furthermore, if the ball moves is outside the rectangle 0 < x < width,
         // 0 < y < height, adjust the sign of the x or y component of the
         // velocity to make the ball head back into the rectangle.  This
         // method is meant to be called once for each frame of the animation.
      g.setColor(color);
      g.fillOval((int)centerX - radius, (int)centerY - radius, 2*radius, 2*radius);
      centerX += velocityX;
      centerY += velocityY;
      if (centerX - radius < 0)
         velocityX = Math.abs(velocityX);
      if (centerX + radius >= width)
         velocityX = -Math.abs(velocityX);
      if (centerY - radius < 0)
         velocityY = Math.abs(velocityY);
      if (centerY + radius >= height)
         velocityY = -Math.abs(velocityY);
   }
   
 
   public void setPosition(int x, int y) {
          // Change position of the ball's center to the specified point, (x,y).
      this.centerX = x;
      this.centerY = y;
   }
   
 
   public void headTowards(int x, int y) {
          // Modify the velocity so that the ball is moving in the direction
          // of the point (x,y).  The speed of the ball does not change, only
          // its direction of motion.  (If the specified point is too close
          // to the current position of the ball, the velocity of the ball
          // does not change.)  This method uses some standard vector mathematics.
      if (Math.abs(x - centerX) < 1.0E-10 && Math.abs(y - centerY) < 1.0E-10)
         return;
      double v = Math.sqrt(velocityX*velocityX + velocityY*velocityY);
      double d = Math.sqrt((x-centerX)*(x-centerX) + (y-centerY)*(y-centerY));
      velocityX = (x-centerX)*v/d;
      velocityY = (y-centerY)*v/d;
   }


} // end class BouncingBall
