import java.awt.*;
import java.applet.*;
import java.util.Random;

/**
 * A simple implementation of a bouncing ball.
 * <p>
 * Copyright (c) 1998 Samuel A. Rebelsky.  All rights reserved.
 *
 * @author Samuel A. Rebelsky
 * @version 1.1 of March 1999
 */
public class BallApplet 
  extends Applet 
  implements Runnable 
{

  // +------------+----------------------------------------------
  // | Attributes |
  // +------------+

  /** The current x position of the center of the ball.  */
  protected int xpos;

  /** The current y position of the center of the ball.  */
  protected int ypos;

  /** The current radius of the ball. */
  protected int radius;

  /** The current horizontal velocity of the ball. */
  protected int horizVelocity;

  /** The current vertical velocity of the ball. */
  protected int vertVelocity;

  /** The color of the ball. */
  protected Color color;

  /** The thread that corresponds to the curent applet. */
  protected Thread thread;


  // +-------------------------+---------------------------------
  // | Standard Applet Methods |
  // +-------------------------+

  /**
   * Initialize the applet.  Set up the color, position, velocity,
   * and such.
   */
  public void init() {
    // To make things interesting, we might initialize some of the values
    // randomly.  This means that we'll need a random number generator.
    Random generator = new Random();

    // Pick a "reasonable" radius
    radius = 10;

    // Start at the upper left-hand-corner
    xpos = 10;
    ypos = 10;
    
    // Start at a moderate velocity
    horizVelocity = 5;
    vertVelocity = 5;

    // Pick a nice color
    color = Color.blue;
  } // init()
  
  /**
   * Paint the ball on the screen.
   */
  public void paint(Graphics g) {
    g.setColor(color);
    g.fillOval(xpos-radius, ypos-radius, 2*radius, 2*radius);
  } // paint(Graphics)

  /**
   * Run the thread.
   */
  public void run() {
    // It appears that we keep going forever.  However, external
    // things (that is, the web browser) control when we stop.
    while (true) {
      try {
        thread.sleep(20);
      }
      catch (InterruptedException ie) {
        // Do nothing
      }
      // Update the position of the ball
      updatePosition();
      // And repaint
      repaint();
    } // while
  } // run()

  /**
   * Start the thread.
   */
  public void start() {
    thread = new Thread(this);
    thread.setPriority(Thread.MIN_PRIORITY);
    thread.start();
  } // start()

  /**
   * Stop the thread.
   */
  public void stop() {
    thread.stop();
  } // stop()


  // +--------------------+--------------------------------------
  // | Additional Methods |
  // +--------------------+

  /**
   * Update the position of the ball.
   */
  public void updatePosition() {
    // We'll need the dimensions of the current window to determine
    // when we reach a wall.
    Dimension dim = this.getSize();
    // Update the x and y position
    xpos = xpos + horizVelocity;
    ypos = ypos + vertVelocity;
    // If we've gone too far in one direction, reverse the ball
    if (xpos+radius > dim.width) {
      xpos = dim.width - (xpos + radius - dim.width);
      horizVelocity = -horizVelocity;
    }
    else if (xpos-radius < 0) {
      xpos = -(xpos - radius); 
      horizVelocity = -horizVelocity;
    }
    if (ypos+radius > dim.height) {
      ypos = dim.height - (ypos + radius - dim.height);
      vertVelocity = -vertVelocity;
    }
    else if (ypos-radius < 0) {
      ypos = -(ypos - radius);
      vertVelocity = -vertVelocity;
    }
  } // updatePosition()
} // BallApplet

