import java.awt.*;

public class BounceOvalCanvas extends Canvas implements Runnable {
    Thread bounce;
    int x;
    int y;
    int speed = 1;
    int theSize = 10;
    Image buffer;
    Graphics bufferG;
    int colorIndex;
    Color[] theColors = { Color.red,Color.blue,Color.cyan,Color.green,Color.yellow,
                          Color.orange,Color.gray,Color.magenta };

    // constructor
    public BounceOvalCanvas (String c) {
        super();
        if( c.equals("red") ) colorIndex = 0;
        if( c.equals("blue") ) colorIndex = 1;
        if( c.equals("cyan") ) colorIndex = 2;
        if( c.equals("green") ) colorIndex = 3;
        if( c.equals("yellow") ) colorIndex = 4;
        if( c.equals("orange") ) colorIndex = 5;
        if( c.equals("gray") ) colorIndex = 6;
        if( c.equals("magenta") ) colorIndex = 7;
    }

    // Where the 'action' is. When the O reaches the border the equation
    // of a new line to bring it back is calculated The slope is random

    public void run() {
        x = 1;
        int xO = 1;
        int yO = 1;
        int increment = speed;
        int yIncrement = speed;
        double angle = Math.PI / 2.0 * Math.random();
        double slope = Math.tan(angle);
        // This is the equation of the initial line
		    if( -1.0 <= slope && slope <= 1.0 ) {
			    y = (int)(slope * (x - xO) + yO);
		    } else {
          x = (int)((1.0/slope)*(y-yO) + xO);
        }
        while( true ) { //Thread.currentThread() == bounce ) {
          if( x <= 0 ) {
            increment = speed;
            if( yIncrement > 0 )
           	angle = Math.PI / 2.0 * Math.random();
          else
           	angle = -Math.PI / 2.0 * Math.random();
          slope = Math.tan(angle);
          xO = x;
          yO = y;
        } // end if
        if( y <= 0 ) {
          if( increment < 0 ) {
             angle = Math.PI / 2.0 * Math.random() + Math.PI /2.0;
          } else {
             angle = Math.PI / 2.0 * Math.random();
          } // end if
				  yIncrement = speed;
          slope = Math.tan(angle);
          xO = x;
          yO = y;
        } // end if
        if( x >= getSize().width - theSize ) {
          increment = -speed;
          if( yIncrement > 0 )
           	angle = Math.PI / 2.0 * Math.random() + Math.PI / 2.0;
          else
           	angle = Math.PI  / 2.0 * Math.random() + Math.PI;
          slope = Math.tan(angle);
          xO = x;
          yO = y;
        } // end if
        if( y >= getSize().height - theSize ) {
				  yIncrement = -speed;
          if( increment > 0 ) {
            angle = Math.PI / 2.0 * Math.random() - Math.PI / 2.0;
          } else {
            angle = Math.PI / 2.0 * Math.random() + Math.PI;
          } // end if
          slope = Math.tan(angle);
          xO = x;
          yO = y;
        } // end if
			  if( -1.0 <= slope && slope <= 1.0) {
				  x += increment;
				  y = (int)(slope * (x - xO) + yO);
			  } else {
				  y += yIncrement;
				  x = (int)((y-yO)/slope + xO);
			  } // end if
        try {Thread.sleep(10);} catch(InterruptedException e){}
        repaint();
        }
    }

    public void update(Graphics g) {
    // this illustrates double buffering
		  if( buffer == null ) {
		  	buffer = createImage(300,300);
		    }
		  bufferG = buffer.getGraphics();
		  //bufferG.setColor(Color.white);
		  //bufferG.fillRect(0,0,300,300);
		  bufferG.setColor(theColors[colorIndex]);
		  bufferG.fillOval(x,y,theSize,theSize);
		  bufferG.dispose();
		  paint(g);
    }

    public void paint( Graphics g ) {
      if( buffer == null ) return;
      g.drawImage(buffer,0,0,null);
   }

}  // end BounceOvalCanvas


