import java.awt.Graphics;
import java.util.*;
import java.awt.*;

/********************************************************************
 *
 * This extension to the Applet class bounces lots of lines around.
 *
 * The size of the box is specified by the 'width' and 'height'
 * values in the applet tag.
 *
 * @author  Dave Wylie
 * @version 0.1, 31-Jul-1996
 *
 ********************************************************************/
public class Sticks extends java.applet.Applet implements Runnable
{
   int theHeight;                // Height of our bounce box
   int theWidth;                 // Width of our bounce box
   int maxX;                     // Maximum X co-ordinate of line end
   int minX;                     // Minimum X co-ordinate of line end
   int maxY;                     // Maximum Y co-ordinate of line end
   int minY;                     // Minimum Y co-ordinate of line end
   final int NUM = 10;           // Number of threads we want
   Thread stickThread[];         // Threads that bounce sticks
   boolean starting;             // Flags if we are starting our threads
   boolean stopping;             // Flags if we are stopping our threads
   Random rand = new Random();   // A new random number object


   /*****************************************************************
    *
    * Applet initialisation routine
    *
    *****************************************************************/
   public void init()
   {
      // Allocate storage for the Threads array - note that
      // this is merely storage space for the array, NOT the
      // thread objects inside it.
      stickThread = new Thread[ NUM ];

      // We are neither stopping nor starting at the moment
      stopping = false;
      starting = false;

      // Get the size of the applet screen area we are to work in
      theHeight =  size().height;
      theWidth  =  size().width;

      // Initialise our bounce points
      minX  = 0;
      maxX  = theWidth;
      minY  = 0;
      maxY  = theHeight;

      // Set the width and height, set background to BLACK
      // and make sure it is visible.
      setBackground( Color.black );
      show( );
   }

   /*****************************************************************
    *
    * Called each time the browser displays the page.
    * For each thread we may have, check if there isn't one running.
    * Create one if necessary and and start it up.
    *
    *****************************************************************/
   public void start()
   {
      int tNum;

      if( !starting )
      {
         starting = true;

         for( tNum = 0; tNum < NUM; tNum++ )
         {
            stickThread[ tNum ] = new Thread( this );
            stickThread[ tNum ].start();
         }

         stopping = false;
      }
   }

   /*****************************************************************
    *
    * Called each time the browser leaves the page.
    * Junk any threads that may be running.
    *
    *****************************************************************/
   public void stop()
   {
      int tNum;

      if( !stopping )
      {
         stopping = true;

         for( tNum = 0; tNum < NUM; tNum++ )
         {
            stickThread[ tNum ].stop();
            stickThread[ tNum ] = null;
         }

         starting = false;
      }
   }

   /*****************************************************************
    *
    * The main thread of execution.
    * While we have a running thread, update the display,
    * sleep for the specified time and go round again.
    * Note that we draw directly onto the Applet's display area
    * (obtained using the getGraphics() method). This is because
    * with lots of independent threads moving lines around, we
    * can't do the drawing in a single paint routine (which is
    * infact called within a Java System thread).
    *
    *****************************************************************/
   public void run()
   {
      int x1;                 // Current X co-ordinate of one end
      int y1;                 // Current Y co-ordinate of one end
      int x2;                 // Current X co-ordinate of other end
      int y2;                 // Current Y co-ordinate of other end
      int x1Dir;              // Current X1 axis step size and direction
      int y1Dir;              // Current Y1 axis step size and direction
      int x2Dir;              // Current X2 axis step size and direction
      int y2Dir;              // Current Y2 axis step size and direction
      Graphics g;

      g = getGraphics();

      // Set up the initial line to have random start and end points
      x1 = Math.abs( rand.nextInt() ) % maxX;
      y1 = Math.abs( rand.nextInt() ) % maxY;
      x2 = Math.abs( rand.nextInt() ) % maxX;
      y2 = Math.abs( rand.nextInt() ) % maxY;

      // Set up our directions a bit randomly too
      x1Dir = Math.abs( rand.nextInt() ) % 5 + 1;
      y1Dir = Math.abs( rand.nextInt() ) % 5 + 1;
      x2Dir = Math.abs( rand.nextInt() ) % 5 + 1;
      y2Dir = Math.abs( rand.nextInt() ) % 5 + 1;

      // This thread keeps running until it is destroyed
      while( true )
      {
         // Overwrite the old line in the background colour
         g.setColor( Color.black );
         g.drawLine( x1, y1, x2, y2 );

         // See if we have reached an edge in either direction
         if( ( x1 >= maxX ) || ( x1 <= minX ) ) x1Dir = -x1Dir;
         if( ( y1 >= maxY ) || ( y1 <= minY ) ) y1Dir = -y1Dir;
         if( ( x2 >= maxX ) || ( x2 <= minX ) ) x2Dir = -x2Dir;
         if( ( y2 >= maxY ) || ( y2 <= minY ) ) y2Dir = -y2Dir;

         // Move along the two co-ordinates in the current direction
         x1 += x1Dir;
         y1 += y1Dir;
         x2 += x2Dir;
         y2 += y2Dir;

         // Draw the new line in WHITE
         g.setColor( Color.white );
         g.drawLine( x1, y1, x2, y2 );

         // The sleep may fail
         try
         {
            // Nap for a while
            Thread.sleep( 100 );
         }
         catch (InterruptedException e)
         {
            // Log any problem on the Java console
            System.out.println( "Exception:  " + e );
         }
      }
   }
}

