import java.awt.Graphics;
import java.awt.Color;
import java.awt.Point;
import java.awt.Image;
import java.awt.event.*;

public class RandomGrid03
  extends java.applet.Applet
  implements MouseListener, MouseMotionListener, Runnable
{
  // graphics buffer vars
  Image offscreenImg;
  Graphics offscreenG;

  // thread vars
  Thread runner;
  int pauseTime = 10;

  // set colors
  Color bgColor = new Color(0x00, 0x00, 0x00);
  Color lineColor = new Color(0xC0, 0xC0, 0xC0);

  // set point array and vars
  Point[] gridPoint = new Point[10000];
  Point nextPoint, lastPoint;
  
  int pointCount = 0;
  int gridSize = 25;
  int gridMagic = 11;
  

  public void init()
  {
    // set offscreen buffer
    offscreenImg = createImage(getSize().width, getSize().height);
    offscreenG = offscreenImg.getGraphics();

    // fill background
    offscreenG.setColor(bgColor);
    offscreenG.fillRect(0,0,getSize().width,getSize().height);
    offscreenG.setColor(lineColor);

    // register event listeners
    addMouseListener(this);
    addMouseMotionListener(this);

    // set starting point
    lastPoint = new Point((int)getSize().width/2, (int)getSize().height/2); 
    nextPoint = new Point(lastPoint.x, lastPoint.y);
  }
  


  public void start() { if (runner == null) {
    runner = new Thread(this);
    runner.start();
  }}
	
  public void stop() { if (runner != null) {
    runner.stop();
    runner = null;
  }}
  

  public Point genNextPoint(Point startPoint)
  {
    Point newPoint = new Point();
    double rot;
    int i;
   
    newPoint.x = -500;
    newPoint.y = -500;
    
    // generate new point, keeping it within view
    while (newPoint.x < - gridSize || newPoint.y < - gridSize
            || newPoint.x > getSize().width + gridSize || newPoint.y > getSize().height + gridSize)
    {
      rot = Math.random() * Math.PI * 2;
      newPoint.y = startPoint.y + (int)Math.round(gridSize * Math.cos(rot));
      newPoint.x = startPoint.x + (int)Math.round(gridSize * Math.sin(rot));
    }
    
    // add new point to array
    gridPoint[pointCount] = newPoint;
    
    // check if new point is near existing point
    // if so, new point becomes existing point
    for (i = 0; i < pointCount; i++)
    {
      if (newPoint.x > gridPoint[i].x - gridMagic && newPoint.y > gridPoint[i].y - gridMagic
            && newPoint.x < gridPoint[i].x + gridMagic && newPoint.y < gridPoint[i].y + gridMagic)
      {
        newPoint.x = gridPoint[i].x;
        newPoint.y = gridPoint[i].y;
        break;
      }
    }
    
    pointCount++;
    
    return newPoint;
  }



  public void run() { while (true) {
    // gen random next point
    if (pointCount < gridPoint.length)
      nextPoint = genNextPoint(lastPoint);
  
    // draw to buffer
    offscreenG.drawLine(lastPoint.x, lastPoint.y, nextPoint.x, nextPoint.y);
    
    // set lastpoint to current point
    lastPoint.x = nextPoint.x;
    lastPoint.y = nextPoint.y;

    // wait a while
    try { Thread.sleep(pauseTime); }
    catch (InterruptedException e) { }
    
    // repaint to draw the modified buffer
    repaint();
  }}
  
  
  
  
  public void update(Graphics g)
  {
    paint(g);
  }

  public void paint(Graphics g)
  {
    // draw the offscreen-buffer with all the lines 'n stuff
    g.drawImage(offscreenImg,0,0,this);
  }






  public void mouseDragged(MouseEvent e) {  }
  public void mouseReleased(MouseEvent e) {  }
  public void mouseClicked(MouseEvent e) {  }
  public void mouseEntered(MouseEvent e) {  }
  public void mouseExited(MouseEvent e) {  }
  public void mouseMoved(MouseEvent e) { }

  public void mousePressed(MouseEvent e)
  {
    // reset point counter
    pointCount = 0;

    // set starting point to mouse position
    lastPoint = new Point(e.getX(), e.getY()); 
    nextPoint = new Point(lastPoint.x, lastPoint.y);

    // fill background
    offscreenG.setColor(bgColor);
    offscreenG.fillRect(0,0,getSize().width,getSize().height);
    offscreenG.setColor(lineColor);
  }

 
}
