import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics;
import javax.swing.*;

public class circles extends JFrame
{
  private Graphics brush;
  public Graphics display;
  private    Image canvas;    // off-screen graphics buffer

  public void paint(Graphics g) {}  // overrides auto-update

  public static void main(String[] args) // needed for application
  {
    circles session  = new circles();
    session.addWindowListener(new WindowAdapter() {
              public void windowClosing(WindowEvent e) {System.exit(0);} });
    session.init();
  }

  public void init()
    {
       setBounds(0,0,800,600);
       show();
       canvas = createImage(800,600);
       brush = canvas.getGraphics();
       display = this.getGraphics();
       brush.setColor(Color.black);   // clear 
       brush.fillRect(0,0,800,600);   // with black background
       brush.setColor(Color.green);   // 
       animate();
    } // init


   private void clearbuffer()
    { Color old;
      old = brush.getColor();
      brush.setColor(Color.black);   // clear 
      brush.fillRect(0,0,800,600);   // with black background
      brush.setColor(old);   //  restores color
    } // clearbuffer

   public void nextframe(int delay) // delay in ms
    {
       try { Thread.sleep(delay); } catch (InterruptedException IE) {}
       display.drawImage(canvas,0,0,null);  // draws to screen
       clearbuffer();
    } // nextframe with ms delay


    /* stuff pertaining to bouncing circles: */

   private int randint(int min, int max) 
    { return (int) (Math.random() * (max-min+1) + min); }

  
   public void animate()
    {  int x1; int y1;   // hold random numbers
       int x2; int y2;
       circle c1, c2;
       c1 = new circle(50,100,30,Color.green,brush);
       c2 = new circle(300,110,20,Color.red,brush);
       c1.setmovement(randint(-9,9),randint(-9,9));
       c2.setmovement(randint(-9,9),randint(-9,9));
       // c1.setmovement(4,0);
       // c2.setmovement(-2,0);
       
       while (1<2)
	   {  
               if (c1.overlap(c2))  // switch movement vectors
		   {   int olddx, olddy;
		       olddx = c1.getdx();
		       olddy = c1.getdy();
		       c1.setmovement(c2.getdx(),c2.getdy());
		       c2.setmovement(olddx,olddy);
		   }
	       c1.draw();
	       c2.draw();
	       c1.move();
	       c2.move();
	       nextframe(40);
           }
    } // animate

} // class circles


class circle
{
  private int x;   // coordinate of center of circle
  private int y; 
  private int radius; // radius of circle
  private int dx;  // movement vector:
  private int dy;
  Color thecolor;     
  private Graphics brush;
  private final int XBOUND = 800;
  private final int YBOUND = 600;

  public circle(int x0, int y0, int r, Color c, Graphics b) // constructor
    { x = x0;  y = y0;
      radius = r;  thecolor = c;
      dx = 0;   dy = 0;
      brush = b;
    }

  public int getx() { return x; }
  public int gety() { return y; }
  public int getr() { return radius; }
  public int getdx() { return dx; }
  public int getdy() { return dy; }

   // returns distance between two points
   private double distance(int x0, int y0, int x1, int y1)  // note private 
    { int x = (x0-x1)*(x0-x1);
      int y = (y0-y1)*(y0-y1);
      return Math.sqrt(x+y);
    }

  public void setmovement(int newdx, int newdy)
    {
      dx = newdx;  dy = newdy;
    }
   
  public void move() // move, bouncing off edges
  { if ( (x >= (XBOUND-radius)) || (x < radius) )
       dx = -1 * dx;  // reverse x direction
    if ( (y >= YBOUND-radius) || (y < radius+30) )
       dy = -1 * dy;  // reverse y direction
    x = x+dx;  y = y+dy;
  }

  public boolean overlap(circle other)
    {
	double dist;
	dist = distance(x,y,other.getx(),other.gety());
	return dist <= radius + other.getr();
    }

  public void draw()
    {
	brush.setColor(thecolor);
	brush.fillOval(x-radius,y-radius,2*radius,2*radius);
    }

}  // class circle
