//************************************************************************ // // Lines.java -- An applet that draws a set of moving lines. // // Copyright 1996, 2001 Mark Edwards/Computer Masters, Inc. // //************************************************************************ import java.applet.*; // for applet shell import java.awt.*; // for graphics routines public class Lines extends Applet implements Runnable { // defaults & constants int TOTLINES = 40; // number of lines on screen int LINESPER = 1; // number of lines per color int MAXRGB = 255; int MINRGB = 0; int COLORSPEED = 1; // added to rgb values boolean HORIZ = true; boolean VERT = false; long PAUSE = 50; // # ms. to yield thread // starting line position, direction and speed short FIRSTX = 10; short FIRSTY = 10; short SECONDX = 250; short SECONDY = 10; // indicies into lines array int X1 = 0; int Y1 = 1; int X2 = 2; int Y2 = 3; // Speed constants for movement of x,y values int ADDX1 = 10; int ADDY1 = 5; int ADDX2 = -5; int ADDY2 = 10; // Properties Thread movelines = null; // drawing thread boolean eraseflag = false; // true after first set of lines drawn boolean firstpaint = true; // false after first time paint is called boolean firstinit = true; // false after first time init is called Image memimage; // Buffer for current screen Graphics memgr; // Graphics context into Buffer int xmin; int xmax; int ymin; int ymax; // initial line color int red = MINRGB; int green = MINRGB; int blue = MAXRGB; int curcolor = 3; // Flag for currently maxed color. 1 = RED, 2 = GREEN, // 3 = BLUE boolean movingup = true; // TRUE if incrementing next color, FALSE if // decrementing previous color // holds a set of moving coord pairs int lines[][] = new int[ TOTLINES ][ 8 ]; int curline = 0; // Major index // // Methods // // // init method. Sets the inital position of the first line. Checks to see if // it has already been called, because of a nasty Netscape bug. // public void init() { if ( firstinit ) { // Set the size of the drawing area Dimension d = size(); xmin = 0; xmax = d.width - 1; ymin = 0; ymax = d.height - 1; // Position first line lines[ 0 ][ X1 ] = FIRSTX; lines[ 0 ][ Y1 ] = FIRSTY; lines[ 0 ][ X2 ] = SECONDX; lines[ 0 ][ Y2 ] = SECONDY; // turn off firstinit firstinit = false; } repaint(); } // // Applet run method. Note that this starts and keeps running until the // applet is destroyed by closing the page. // public void run() { Thread.currentThread().setPriority( Thread.MIN_PRIORITY ); // infinite loop while ( true ) { repaint(); try { Thread.sleep( PAUSE ); } catch( Exception e ) { } } } // // Applet start method. Creates a new thread for the graphics routines to run // in, and starts that thread. Checks first to see if the thread already exists // so multiple calls will not create multiple threads. // public void start() { if ( movelines == null ) { movelines = new Thread( this ); movelines.start(); } } // // Applet stop method. Sets the handle for the thread that runs the graphics // routines to null, allowing the JVM to kill it. // public void stop() { movelines = null; } // // paint -- draws the image currently in the memory buffer. The first time this // is called, it creates and initializes the buffer. // public void paint( Graphics g ) { if ( firstpaint ) { // create a new image & Graphics ojbect memimage = createImage( xmax + 1, ymax + 1 ); memgr = memimage.getGraphics(); // set the background memgr.setColor( Color.black ); memgr.fillRect( 0, 0, xmax + 1, ymax + 1 ); // turn off firstpaint tasks firstpaint = false; } // draw the image into the screen g.drawImage( memimage, 0, 0, this ); } // // update -- Redraws the drawing area, erasing old lines and drawing new ones. // public void update( Graphics g ) { int nextline; // exit if memimage not built yet if ( memgr == null ) return; // set the next color nextcolor( memgr ); // draw the current line memgr.drawLine( lines[ curline ][ X1 ], lines[ curline ][ Y1 ], lines[ curline ][ X2 ], lines[ curline ][ Y2 ] ); // check next line nextline = (( curline + 1 ) % TOTLINES ); // wrap to beginning of array // Possibly erase the last line. At startup, we draw one line each time // until we have a line for each slot in the array. After that we draw // each new line, and erase the last line, to keep the number of lines // on the screen equal to the number of array slots. if ( !eraseflag ) { // check to see if we're starting the second pass if ( nextline == 0 ) { eraseflag = true; } } if ( eraseflag ) { // erase the last line line memgr.setColor( Color.black ); memgr.drawLine( lines[ nextline ][ X1 ], lines[ nextline ][ Y1 ], lines[ nextline ][ X2 ], lines[ nextline ][ Y2 ] ); } // Calc next line's position, and store in array. Check for edge // collision, and randomly change direction. // first do startpoint lines[ nextline ][ X1 ] = ( short )( lines[ curline ][ X1 ] + ADDX1 ); lines[ nextline ][ Y1 ] = ( short )( lines[ curline ][ Y1 ] + ADDY1 ); // check if we've hit an edge if ( isAtEdge( lines[ nextline ][ X1 ], HORIZ )) { // reverse direction ADDX1 *= -1; lines[ nextline ][ X1 ] += ADDX1; // possibly reverse other endpoint's direction if (( Math.random() > 0.5 ) && ( !isAtEdge( lines[ nextline ][ X2 ] - ADDX2, HORIZ ))) { ADDX2 *= -1; } } if ( isAtEdge( lines[ nextline ][ Y1 ], VERT )) { ADDY1 *= -1; lines[ nextline ][ Y1 ] += ADDY1; if (( Math.random() > 0.5 ) && ( !isAtEdge( lines[ nextline ][ Y2 ] - ADDY2, VERT ))) { ADDY2 *= -1; } } // now do endpoint lines[ nextline ][ X2 ] = ( short )( lines[ curline ][ X2 ] + ADDX2 ); lines[ nextline ][ Y2 ] = ( short )( lines[ curline ][ Y2 ] + ADDY2 ); // check if we've hit an edge if ( isAtEdge( lines[ nextline ][ X2 ], HORIZ )) { ADDX2 *= -1; lines[ nextline ][ X2 ] += ADDX2; if (( Math.random() > 0.5 ) && ( !isAtEdge( lines[ nextline ][ X1 ] - ADDX1, HORIZ ))) { ADDX1 *= -1; } } if ( isAtEdge( lines[ nextline ][ Y2 ], VERT )) { ADDY2 *= -1; lines[ nextline ][ Y2 ] += ADDY2; if (( Math.random() > 0.5 ) && ( !isAtEdge( lines[ nextline ][ Y1 ] - ADDY1, VERT ))) { ADDY1 *= -1; } } // increment to nextline curline = nextline; // display the new image g.drawImage( memimage, 0, 0, this ); } // // nextcolor -- increments the current drawing color // // Start with RED all the way up, GREEN and BLUE all the way down. Bring // GREEN up, then bring RED down. Bring Blue up, then bring GREEN down. // Bring RED up, then bring BLUE down. // public void nextcolor( Graphics g ) { // calc color for current line if (( curline % LINESPER ) == 0 ) { // bump to next color if ( movingup ) { switch ( curcolor ) { case 1: // RED if ( green >= MAXRGB ) { curcolor++; movingup = false; } else { green += COLORSPEED; if ( green > MAXRGB ) { green = MAXRGB; } } break; case 2: // GREEN if ( blue >= MAXRGB ) { curcolor++; movingup = false; } else { blue += COLORSPEED; if ( blue > MAXRGB ) { blue = MAXRGB; } } break; case 3: // BLUE if ( red >= MAXRGB ) { curcolor = 1; movingup = false; } else { red += COLORSPEED; if ( red > MAXRGB ) { red = MAXRGB; } } break; } } else { switch ( curcolor ) { case 1: // RED if ( blue <= MINRGB ) { movingup = true; } else { blue -= COLORSPEED; if ( blue < MINRGB ) { blue = MINRGB; } } break; case 2: // GREEN if ( red <= MINRGB ) { movingup = true; } else { red -= COLORSPEED; if ( red < MINRGB ) { red = MINRGB; } } break; case 3: // BLUE if ( green <= MINRGB ) { movingup = true; } else { green -= COLORSPEED; if ( green < MINRGB ) { green = MINRGB; } } break; } } // set the color Color temp = new Color( red, green, blue ); g.setColor( temp ); } } // // isAtEdge -- returns TRUE if a point has hit an edge of the drawing // area. If HORIZONTAL is true, then we test for the left & right edges, // else we test for the top & bottom edges. // public boolean isAtEdge( int point, boolean horizontal ) { int min, max; if ( horizontal ) { min = xmin; max = xmax; } else { min = ymin; max = ymax; } if ( point <= min || point >= max ) { return true; } else { return false; } } }