Introduction to Java. A tutorial from A-SQUARE, Inc. January 2003

© 2000-2003 A-Square, Inc.

Source Code for Lines.java and EndPoint.java

This code is used in Exercise 5b. It includes the code for the Lines universe as well as for the class EndPoint

Note the three main sections of a Rart universe:

Section 1 Identifying the universe

Section 2 What the universe does

Section 3 uParameters as used in the universe

Lines.java

>

/*
 * @Lines    2.1  001207
 *
 * © A-Square, Inc. 1996-2000
 * 1648 Waters Edge Lane, Reston Virginia, 20190, USA
 */

import java.awt.*;
import java.lang.*;
import rartbase.*;
/**
 * Lines universe
 *	 
 * Source: Lines.java
 * Description: Displays a window with lines that wander across the screen.
 * When the endpoints rech the border, they bounce off in random directions.
 * There are a number of lines on the screen at the time and they change 
 * color as they progress.
 *		
 *	 Author: Jan Aminoff
 * This version is a cleaned up version of the original Lines universe
 * programmed in QuickBasic for the Mac in 1987 or so. and reprogrammed in
 * Java around 1996. 
 *
 * Version 2.1 added ability to change background etc.
 * Used as exercise 5b in the Introduction to Java tutorial
 */


public final class Lines extends Universe {
	
	// Section 1     Identifying the Universe
	// ------------------------------------------------------------------------
	
	public String getName(){	// Name
    	return("Lines");}       // Name of the universe.
    public String getDescription(){
    	return(sd);}            
    private String sd=			// Description
    		"  See the Lines Universe where two end points go straight, "+
            "stepped in discrete steps until they bounce randomly "+
            "against the edge of the window. Lines join the two end "+
            "points for each step and the resulting patterns can be "+
            "quite beautiful. ";                                 
    public String getRartist(){
    	return("Jan Aminoff 2000");}  // Name of Rartist.
    	
    // end of Section 1
    
	// Section 2    What the universe does
	// -----------------------------------------------------------------------
	
	private static int nn_max=300; // Maximum number of lines
	// The endpoints of the lines are saved in the following two point arrays
	private Point p1s[] = new Point[nn_max];
	private Point p2s[] = new Point[nn_max];
	// The EndPoints are the ones moving generating new lines as they move
	private EndPoint p1;  // first EndPoint
	private EndPoint p2;  // second EndPoint
  
	private int m;		// current index to point array
	
	private boolean resetScreen=false;  // Flag to reset the screen as needed.
	
	private Debug dB;   // Not used but here if needed. See init.
	
	public void init(){
	    /* 
	    // Following establishes a pattern for setting and use of Debug.
	    // Debug is not used in this release of the Lines universe.
		 dB=new Debug();
		 int dblevel=2
		 dB.setLevel(dblevel);
		 dB.dbg(1,"Debug Level now set to "+dblevel");
		 */
		setParams();
		reset();
	}
	
	/**
	 * reset is used in init and also in manageChange when uParameters speed
	 * (with index VIEWSIZE) and number (with index NUMBER) have changed.
	 */
	private void reset(){
		vv = speed.getCur();	// current maximum speed
		nn = number.getCur();	// current number of lines
		// xm and ym are available from universe
		p1 = new EndPoint(xm,ym,vv); // first EndPoint 
		p2 = new EndPoint(xm,ym,vv); // second EndPoint
		m=0;		// index to current pair of endpoints
		// reset the arrays of points
		for (int i = 0; i<nn; i++){
			p1s[i]=new Point(0,0);
			p2s[i]=new Point(0,0);
		}
		// The following deals with the new ability to select color 
		// combinations as introduced in Ex5b of Intro to Java
		cc=colorcomb.getCur();
		if (cc==0) {
		    colorlines = false;
		    lineColor = Color.black;
		    background = Color.white;
		}else if (cc==1){
		    colorlines = false;
		    lineColor = Color.white;
		    background = Color.black;
		}else{
		    colorlines = true;
		    background = colors[cc-2];
		}
		// end of Ex5b addition
		resetScreen=true;
	}	//end of reset
	
	public void cycle (Graphics g){
	    if (resetScreen){
		     g.setPaintMode();
		     g.setColor(background);		     
			 g.fillRect(0,0,xm,ym);
			 resetScreen = false;
		}
		// Save p1 and p2 as points in point arrays
		p1s[m]=new Point(p1);
		p2s[m]=new Point(p2);
		//Update position of the two end points
		p1.move();
		p2.move();
		// Step index to point arrays
		m= (m+1) % nn; 
		// If we have been there, disappear the former line
		if ((p1s[m].x!=0)&& (p1s[m].y!=0)){
			g.setColor(background);
			g.drawLine(p1s[m].x, p1s[m].y, p2s[m].x, p2s[m].y);
		}
		if (colorlines) {
		    // Step line color
		    hue++;
		    lineColor = 
			    Color.getHSBColor((float)(hue/ 360.0),(float)1.0,(float)1.0);
		    hue = hue % 359;	// keep going around the color wheel.
		}
		// Draw Line in color p1 to p
		g.setColor(lineColor);
		g.drawLine(p1.x, p1.y, p2.x, p2.y);
	}	// end of cycle		
	
	// Color stuff
	/* In the enhancement introduced as Ex5b there are three variations of
	 * the Lines universe: Black lines on white, white lines on black, and 
	 * lineColor stepped through 256 colors on a selectable background.
	 * The third version is distingushed by the boolean colorlines being true.
	 * The first two versions are distinguised by colorlines being false and 
	 * the boolean blackonwhite being either true or false.
	 *
	 * Default is colorlines being true.
	 */
	private int cc=2;   //Default choice of linecolor varying on black
	private boolean colorlines=true;
	private boolean blackonwhite;
	// Following prescribed by Universe as released in RDK 1.0 beta
	public Color getBackground(){return background;}
	private Color background = Color.black; //Reset in reset
	private Color lineColor = Color.red;    //
	private int hue = 270;
	
	public void manageChange(uParameter uP){
		int idx=uP.getIndex();
		//dB.dbg( 2,"In Lines, Change in : "+uP.getName());
		if (uPs[idx]!=null) uPs[idx]=uP; //ensures that uPs, the list of current parameters is up to date			
		switch (idx){
			case VIEWSIZE:
				//no problem  since the points gravitate toward the middle
				// but need to reset the screen and reinitialize
				reset();
				break;
			case NUMBER:
				number=uP;
				reset();
				break;
			case PARA4:	 //used for speed or actually density
				// do not need to reset here but need to reset max speed in 
				// the two EndPoint
				speed=uP;
				vv=speed.getCur();
				p1.setMaxSpeed(vv);
				p2.setMaxSpeed(vv);
				break;
			case PARA5: // for new colorcombinations as in Ex5b
			    colorcomb=uP;
			    reset();
			    break;
			}
			
		}   // end manageChange
	// end of Section 2		   
      
	// Section 3   uParameters as used in the universe
    // -----------------------------------------------------------------------
    
    private uParameter number;	//Number of lines requested - PARAMETER
	private int nn_min=2,nn_cur=150;	// nn_max is a static variable	
	private int nn=nn_cur;						//actual number of lines
	private String ndescr=	
			"This parameter indicates the number of 'Lines' on the "+
			"screen at any one time. The number of visible lines remains "+
			"constant after initial growth to the maximum.";
			
	// max speed of any EndPoint in x or y direction - PARAMETER
	private uParameter speed; 
	private int vv=12,vv_max=20,vv_min=1;	  
	private String sdescr= 
			"The 'Speed' is the maximum speed in pixels in the x or the y "+
			"directions. Higher speeds tend to give a clutterd look.";
	
	// colorcombinations of linecolor on background color - PARAMETER
	// The following is new for Ex5b:
	private uParameter colorcomb;
	private String ccdescr=
       "Select line colors against a background from one of the following: "+
       "Black lines on white background, white lines on black, or lines "+
       " whose color is stepped through 26 shades of color against a "+
       "background selected from the thirteen primary Java colors.";
      
   static String colornames[]={ " Black on White", " White on Black",
       " Black background"," Blue background"," Cyan background",
       " Dark grey background", " Grey background",
       " Green background"," Light grey background"," Magenta background",
       " Orange background", " Pink background"," Red background",
       " White background"," Yellow background"};
       
  static Color colors[]=      // Standard Java Colors
        {Color.black,Color.blue,Color.cyan,Color.darkGray,Color.gray,
      Color.green,Color.lightGray,Color.magenta,Color.orange,Color.pink,
      Color.red,Color.white,Color.yellow };
   // end of this addition for Ex5b
	
	// cycletime is set here but otherwise handled in the rartrunners
	public uParameter cycletime;

    private void setParams(){
        number= new uParameter 
        		(NUMBER,"Number of Lines",nn_min,nn_cur,nn_max,ndescr);
        // The adduParameter() method is defined in Universe
        adduParameter(number);     
        speed=new uParameter(PARA4,"Speed",vv_min,vv, vv_max, sdescr);
        adduParameter(speed);
        // The following two statements are new for Ex5b:
        colorcomb = new uParameter
                (PARA5,"Color Combination",cc,colornames, ccdescr);
        adduParameter(colorcomb);
        // Since "Cycle Time" is a compulsory parameter, Universe actually
        // provides the  description 
        cycletime= new uParameter(CYCLETIME,"Cycle Time", 10,25,100, CycleTimeDescr);   
        adduParameter(cycletime); 
   } // end of params
   public Lines() throws InstantiationException {}
}	// end of class Lines
 >
EndPoint.java
>

import java.awt.*;
import rartbase.*;

/** -----------------------------------------------------------------------
 *	 Class: EndPoint, the EndPoint moves in steps of fixed increments (or  
 * speed)across the screen until it hits a border when it is redirected in 
 * a new direction with a new speed.
 */
 
class EndPoint extends Point {
    public static int BORDERWIDTH=20; // EndPoints bounce when coming within 
				// BORDERWIDTH pixels of any edge of the screen
	private int bw=BORDERWIDTH;		// just to save typing
	private int dx;		    // current velocity in x dir
	private int dy;		    // current velocity in y dir
	private int xm; 		// width of window set in constructor
	private int ym;			// height of window set in constructor
	private int vv;			// maximum speed of point set in constructor
	
	
	/**
	 * Constructor
	 * The initial poition of an endpoint is within the rectangle described by
	 * (bw, bw, x_max-2*bw, y_max-2*bw) where bw is the BORDERWIDTH.
	 *
	 * @x_max	the width of the window in pixels
	 * @y_max	the height of the window in pixels
	 * @v_max	the maximum stepping speed of the EndPoint
	 */
	EndPoint(int x_max, int y_max, int v_max) {
		xm=x_max;
		ym=y_max;
		vv=v_max;
		setMaxSpeed(vv);
		x = bw+RND(x_max-2*bw);
		y = bw+RND(y_max-2*bw);
		dx = setSpeed(vv);
		dy = setSpeed(vv);
	}   // end EndPoint constructor
	
	/**
	 * sets the maximum speed in x and y direction
	 * 
	 * @v	speed, greater than 0 and smaller than 50
	 */
	public void setMaxSpeed(int v){
		v= (v<1)? 1: (v>50)? 50: v;
		vv=v;
	}   // end setMaxSpeed
	
	/**
	 * The move method encapsulates the behaviour where a point is stepped in
	 * discrete increments (dx and dy) until it hits an edge when its 
	 * direction is reversed and the speed paralell to the edge given a new
	 * random value, effectively bouncing the point at random.
	 *
	 */
	public void move(){
		x += dx;							//Step x
		y += dy;							//Step y
		// Check to see if the point hit the edge in x-direction
		if (x < bw || x > (xm - bw)){		 
			dx = (x<bw)? ABS(dx):-ABS(dx);  // always moving toward center
			x += 2*dx;						// double back
			dy = setSpeed(vv);				// change speed in y-direction
		}
		// Check to see if the point hit the edge in y-direction
		if (y < bw || y > (ym - bw)){		
			dy = (y<bw)? ABS(dy):-ABS(dy);  // always moving toward center
			y += 2*dy;						// double back
			dx = setSpeed(vv);				// change speed in x-direction
		}
	}	// end move
	
	// Following two methods taken from Universe
	private static int RND(int x){
		 return(Universe.RND(x));
	}
	private static int ABS(int x){
		 return(Universe.ABS(x));
	}
	
	private int setSpeed(int v){
		int v1;
		do{					
			// The following ensures speed distributed randomly in the
			// interval [-v , v] endpoints included and 0 excluded.
			v1=(RND(3)-1)*(1+RND(v));
		}while (v1==0);   // speed never 0!
		return v1;
	} // end of setSpeed
	
}	// end of EndPoint

>