import java.awt.*;
import java.awt.event.*;

public class pendulums extends java.applet.Applet
implements Runnable, MouseMotionListener, MouseListener

{
  int h, w;
  float nowtime;
  Graphics offscreen;
  Image buffer;
  Thread animate;
  
  int MAX = 100;
  Pendulum roy[] = new Pendulum[MAX];
  int xinit, yinit, xcur, ycur;
  Color pend = new Color(255,255,255);
  Color bkg = new Color(51,51,51);
  boolean dragging = false;
    
  public void init()
    {
      int i;
      addMouseMotionListener(this);
      addMouseListener(this);
      Rectangle clip = getBounds();
      h = clip.height;
      w = clip.width;

      buffer = createImage(w,h);
      offscreen = buffer.getGraphics();
    }

  public void paint(Graphics g)
    {
      offscreen.setColor(bkg);
      offscreen.fillRect(0, 0, w, h);
      offscreen.setColor(pend);
      if (dragging) offscreen.drawLine(xinit,yinit,xcur,ycur);
      for(int i=0;i<MAX;i++) if (roy[i] != null) roy[i].swing(offscreen, nowtime);
      
      g.drawImage(buffer, 0, 0, this);
      Toolkit.getDefaultToolkit().sync();
    }

  public void mousePressed(MouseEvent e)
    {
      xcur = xinit = e.getX();
      ycur = yinit = e.getY();
      
      dragging = true;
    }

  public void mouseDragged(MouseEvent e) 
    {
      xcur = e.getX();
      ycur = e.getY();
    }

  public void mouseReleased(MouseEvent e)
    {
      int x = e.getX();
      int y = e.getY();
      
      for(int i=0;i<MAX;i++) if (roy[i] == null) 
        {
          roy[i] = new Pendulum(x,y,xinit,yinit, nowtime);
          i = MAX;
        }
      dragging = false;
    }
    
  public void start()
    {
      if (animate == null)
	{
	  animate = new Thread(this);
	  animate.start();
	}
    }

  public void stop()
    {
      if (animate != null) animate = null;
    }

  public void update(Graphics g) { paint( g ); }
  public void run()
    {
      long then, epoch;
		
      epoch = System.currentTimeMillis();
      while ( animate == Thread.currentThread() ) 
        {
          then = System.currentTimeMillis();
          nowtime = (float) ( (then-epoch)/1000.0f );
          paint(this.getGraphics());
          try { Thread.sleep(5); }
          catch (InterruptedException e) { }

        }
    } 
  public void mouseClicked(MouseEvent e) {}
  public void mouseEntered(MouseEvent e) {}
  public void mouseExited(MouseEvent e) {}
  public void mouseMoved(MouseEvent e) { }
}


class Pendulum
{
  private double thetamax, length, omega;
  private float inittime;
  private int xp, yp;
  private static float animspeed = 3.8f;
  private static double g = 9.81;

  Pendulum(int xknot, int yknot, int xp, int yp, float inittime)
    {
      this.xp = xp; this.yp = yp; this.inittime = inittime;
      
      double dx = xknot-xp;
      double dy = yknot-yp;
      
      if ( (dx == 0.0) && (dy == 0.0) ) dy = 0.001;

      thetamax = Math.atan( dx/dy );
      length = Math.sqrt(dx*dx + dy*dy);
      omega = Math.sqrt( g/length );
    }

  public void swing(Graphics cur, float nowtime)
    {
      double time = nowtime - inittime;
      double theta = thetamax * Math.cos(omega*time*animspeed);
      double x = length*Math.sin(theta);
      double y = length*Math.cos(theta);

      cur.drawLine(xp,yp,(int) (xp+x), (int) (yp+y));
     
      // cur.drawString("Theta    " + theta,50,50);
      // cur.drawString("ThetaMax " + thetamax,50,62);
      // cur.drawString("X " + (xp+x),50,74);
      // cur.drawString("Y " + (yp+y),50,86);
    }
} 
