Uploaded to www.rart.com/j2me-presentation/html_Source/ March 19, 2002

The Abstract Class Universe

This class provides the template for a Rart universe in the AWT environment

This version will be part of the RDK 2.0 release, Spring 2002. It requires JDK 1.1, and has been tested with JDK 1.1.8.

/*
 * @Universe	 1.5	011201
 *
 * © A-Square, Inc.	
 * 1648 Waters Edge Lane, Reston Virginia, 20190, USA 
 */
package rartbase;
import java.awt.*;
import java.util.*;
import java.awt.image.*;


/**
 * Universe
 * An abstract class defining the common properties of all Rart universes
 *
 * @version 1.5  011201
 *
 * @author Jan Aminoff
 *
 * This abstract class allows the RartRunners to control the execution of any 
 * universe extending Universe. It is the key to the Rart concept as 
 * implemented in Java and forms an integral part of the Rart Development Kit.
 *
 * In July: Changed Set extents and commented out (Temporarily?) throwing an 
 * exception when instantiated more than once. It caused problems when NN is 
 * the default browser and you try to start by doubleclicking the HTML startup.
 *
 * Version 1.5 
 *	- 	Reinstated the constructor throwing an exception when more than
 * 	one universe invoked.
 * -  The Demo RR uses the uPs directly to generate random current values for
 *		the uParameters defined for the universe. This violates the OO 
 *	 	methodology. The array is protected private as of now.
 * -	Comments adjusted to fit the 1.5 release of Lines
 * -	Generalized the import of resources which now in a unified way deals
 *		with text (txt), image (gif), and sound (au) files. this uses
 *		the getResource method of the class Class, which was introduced with 
 *		JDK 1.1 making the class and its progeny not executable under 
 *		JDK 1.0.2. (unless RR was compiled under 1.1+ and the universe 
 *		under execution does not request any resources).
 *		See methods getReFileNames,
 * Released as part of RDK 1.5
 * 
 */

public abstract class Universe extends Component{

	// Section 1	Identifying the universe
	// Three simple public abstract methods getName, getDescription, getRartist
	// ------------------------------------------------------------------------
	/**
	 * Provides the name of the univese as an arbitrary string (not to be 
	 * confused with the name of the class extending Universe).
	 *
	 * @return 	String. Name of the universe using no more than 20 characters.
	 */
	public abstract String getName();				 
	 /* Sample code for getName:
		public String getName() {return("Lines");}	  
	 */
	
	 /**
	  * Provides a description of the universe as a textstring.
	  *
	  * @return String. 	Description of the universe using no more than 400 
	  *						characters.
	  */
	public abstract String getDescription();	 
	/* The description will be presented in the About dialog in 12 point 
	 * sansserif on 360 pixel wide lines broken at nearest space. 
	 * Explicit line breaks, '\n', are eliminated.
	 * Sample code for getDescription:
	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. ";   
	 */ 
	/**
	 * Provides the name of the creator of the Universe as well as possibly 
	 * the year of creation or other supplemental information.
	 *
	 * @return 	String. 	Name of Rartist, using no more than 24 characters.
	 */
	public abstract String getRartist();		 
	/* Sample code for getRartist:
		public String getRartist() {return("Jan Aminoff 1989");}
	 */

	
	// Section 2	What the universe does
	// public abstract methods init, cycle, manageChange, and 
	// public getBackground  
	// ------------------------------------------------------------------------
	/**
	 * Method used by the RartRunner class to initialize the universe.
	 * It is executed when the universe is executed the first time.
	 */
	public abstract void init();				
	/* 
	 * The sample universes all have init() methods that allow restart using a
	 * reset() method, that follows a setParam() method taking care of 
	 * of uParameters using default values or values given as HTML Applet tag 
	 * parameters when run as applet or as command line parameters when run as 
	 * an application.
	 * The reset() method may also be used if some parameter has changed and
	 * the reasonable way to manage the change is to restart the universe.	  
	 */
	
	/**
 	 * The main cycle that is executed over and over to provide the animation.
	 * It uses the graphics context g to draw and redraw the screen.
	 *
	 * @param Graphics g	The graphics context
	 */
	public abstract void cycle(Graphics g);		
	/* 
	 * Normally, it is expected that g would be associated with an
	 * off screen image for double buffering. This results in the animation being
	 * smooth but requires some additional memory. If the redrawing is local
	 * and complex it may be preferrable to forgo double buffering and do the
	 * updating locally. The variable public boolean doublebuffer is set to
	 * true (see below) to request double buffering but has to be set to false
	 * if double buffering is not desired.
	 *
	 * cycle(g) is invoked periodically with the priod determined by the 
	 * uParameter with the index CYCLETIME by the RartRunners. 
	 * The Rartist provides anything that shows on the screen in the
	 * cycle(g) method. See the examples.
	 */

	/**
	 * Unified way of handling any observer initiated modifications through
	 * uParameters. The uParameter p provides the new current value.
	 *
	 * @param uParameter p	The uParameter modified by the observer.
	 */
	public abstract void manageChange(uParameter p);  
	/* This is the method invoked by the RartRunners to inform the universe 
	 * that the value of a uParameter has changed. p provides the new value.
	 * The following sample code from the Lines universe deals with change in 
	 * the size of the window (uParameter index VIEWSIZE)and changes in the 
	 * two parameters, "Number of Lines" (uParameter index NUMBER)and 
	 * "Size/Speed" (uParameter index PARA4). The user can reset the color
	 * combinatins of forground background (uParameter index PARA5).
	 * Any changes to "Cycletime" (uParameter index CYCLETIME) in this case,
	 * and probably most cases, are handled by the RartRunner program.
    * See also Section 3 below for the definition of the uParameters.
	 * See sample code from Lines for manageChange: 

	public void manageChange(uParameter uP){
		int idx=uP.getIndex();
		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 p1 and p2.
				speed=uP;
				vv=speed.getCur();
				p1.setMaxSpeed(vv);
				p2.setMaxSpeed(vv);
				break;
			case PARA5: // for new colorcombinations
			   colorcomb=uP;
			   reset();
			   break;
			}	
		}   // end manageChange
	*/

	/**
	 * Provides the default background color.
	 * 
	 * @return Color 	background color
	 *
	 * NOTE: This method is provided for compatibility with some older 
	 * 		universes. As of V 1.4 the universe provides any background
	 *			color.
	 */
	public Color getBackground(){return Color.white;};		 
	/* Provides your default background color. This method was changed from
	 * abstract to this one returning white, 000928. It maintains compatibility
	 * with existing older universes which overrides it when needed.
	 *
	 * The RartRunners were modified 000928 so that they do not color the back-
	 * ground. As of 000928 that responsibility has moved to the cycle() method 
	 * of the universe.
	 */

	
	/* Section 3	uParameters as used in the universe	
 	 *
	 * The uParameters are the mechanism whereby the observer changes the 
	 * universe within the limits set by the Rartist. There are up to 10 
	 * parameters in a Rart universe. They are indexed with a parameter 
	 * index from 1 through 10. (Parameter index UNIV is used 
	 * within the RartRunners only)
	 */
	// ------------------------------------------------------------------------

	public static final int	 NUMBER_OF_PARAMETERS = 10;
	
	// uParameter indicies are named according to anticipated use:
	
	public static final int UNIV=0;			// Used to communicate within RRs
	public static final int VIEWSIZE=1;		// Used for size of window
	public static final int CYCLETIME=2;	// Used for cycletime
	public static final int NUMBER=3;		// Used for number of objects
	public static final int PARA4=4;
	public static final int PARA5=5;
	public static final int PARA6=6;
	public static final int PARA7=7;
	public static final int PARA8=8;
	public static final int PARA9=9;
	
	// to allow setting of the parameters we also need the index as string
	public static final String indexes[]={"UNIV","VIEWSIZE","CYCLETIME",
		 "NUMBER","PARA4","PARA5","PARA6","PARA7","PARA8","PARA9"};
	/**
	 * used to get the string associated with the uParameter index
	 *
	 * @param index	One of the indeces UNIV . . . PARA9
	 * @return String	The string coresponding to the index "UNIV" . . . "PARA9"
	 */
	public static String getIndex(int index){
			  return indexes[index];
	}
	
	/*
	 * The array of all uParameters, the value of undefined uParameters is NULL
	 */
	public uParameter uPs[] = new uParameter[NUMBER_OF_PARAMETERS];

	/**
	 * The array of all uParameters for the universe is available to the
	 * RartRunners thhrough this method.
	 *
	 * @return uParameter[]		the array of uParameters
	 */
	public uParameter[] getuParameters(){
		return uPs;
	} 
	
	
	/*
	 *
	 * Sample code about parameters: Each uParameter has to be declared and set.
	 * The sample code includes the initial declaration of the parameters,
	 * and the code to set or reset them in init(). The sample code is from the 
	 * Lines universe where the settings are collected in the setParam() method.
	 *
	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
	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 };
	
	// cycletime is set here but otherwise handled in the rartrunners
	private 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);
        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 setParams
		 
	 */

	protected static final String CycleTimeDescr =
			"If you have a really fast computer/browser/Java combination "+
			"you can let the universe execute at the higest speed or, which is "+
			"the same thing, the shortest cycle time. But if your equipment/ "+
			"software is slow, you may not see much difference. Try it out! ";
	
	public void adduParameter( uParameter p){
			if (p.getIndex()<uPs.length) 
				uPs[p.getIndex()]=p;
	 }

	// Section 4	Utility Methods
	
	/* The following methods are useful in developing Rart universes
	 * The simple forms occuring here can be overridden or replaced by
	 * more complex forms if desired.
	 * RND, SIGN, and ABS provide a unified way to describe randomness
	 * printString is used for standardized output of text
	 * getImageFileName and getSoundFileName are used to provide the names
	 * of the files of images or sounds to be displayed
	 */

	/**
    * RND - returns a pseudorandom value noless than 0 and less than 
	 * x if x is non negative and a pseudorandom value greater than x
	 * and no greater than 0 if x is non postitive (CF Quickbasic RND)
	 *
	 * @param	x 	any integer
	 * @return		pseudorandom value 
	 */	 
	public static int RND(int x){
		/* See an excellent discussion of random number generators in 
	    * JDC Tech Tips September 25, 2001.
 		 */
		return (SIGN(x)*((int)( Math.random()*ABS(x))));
	}

	/**
	 * returns signum(x)
	 *
	 *	@param 	x	any integer
	 * @return	1 if x>0, -1 if x<0 and 0 if x equals 0
	 */
	public static int SIGN(int x){
		return ((x>0)? 1:(x<0)? -1:0);
	}
	/**
	 * returns absolute value of x
	 *
	 * @param 	x 	any integer
	 * @return 		-x if x<0, otherwise x
	 */
	public static int ABS(int x){
		return ((x>0)? x: -x);
	}
	
	/**
	 * The printString method is used to provide text output within a universe.
	 * The text is rendered on the screen in blue bold proportional sans serif
	 * font stating at x,y and in fontsize as desired. The method assumes that 
	 * you do your own  partitioning of a multiline string by providing
	 * explicit line breaks "\n". It may be invoked in the cycle method to
	 * provide output in a standardized way.
	 *
	 * @param Graphics g		presumably the g provided in the cycle metod
	 * @param String st		the string to be output; can be multiline with 
	 * 							explicit line breaks "\n"
	 * @param x,y				starting coordinates for the rendered string
	 * @param fontSize		size of font in points
	 */
	public static void printString
			(Graphics g, String st, int x, int y, int fontSize){	
		String s=st;
		int i=1, ln=0;
		Font	font = new Font("SansSerif", Font.BOLD, fontSize);
		g.setFont(font);
		g.setColor(Color.blue);
		while (i>0){
			i=s.indexOf("\n",0);
			if (i>1){
				g.drawString(s.substring(0,i), x, y+ln*(fontSize+2));
				s=s.substring(i+1,s.length());
				ln++;				
			}else g.drawString( s, x, y+ln*(fontSize+2) );
		}
	}	// end printString

	// Handling of resources
	/*
	 * When a universe is executing in an applet environment, the RartRunner
	 * has to request any files that are needed. Accordingly the universe 
	 * itself has to inform the RartRunner by giving the filenames of all 
	 * resource files by redefining the reFileNames array of filenames which
	 * is initiated in Universe as a one element array with the value null.
	 * The RartRunner calls getreFileNames and works through the array of 
	 * resource files, each one of which may be either a textfile, an image, 
	 * or a soundclip, identified for now by file extensions txt, gif, or au,
	 * respectively. The loaded resources are made available to the universe 
	 * by the RartRunner executing the setResourceObject method which provides
	 * the loaded resources as an array of objects. It is up to the universe
	 * to deal with each object appropriately, which includes casting the 
	 * the object to the resource actually used.
	 */

   

	/**
	 * This method is invoked by the RartRunner immidiatly after the execution
	 * of the init method of the universe. If the universe 
	 * requires one ore more resource files, the protected String array 
	 * reFileNames should be set by the universe to the names of the required 
	 * resourcefiles. Otherwise and as soon as the files have been sucessfully
	 * loaded, the imageFileNames should be set to contain only one element with 
	 * the value null.
	 *
	 * @return String reFileNames	set in init 
	 */
	public String[] getreFileNames(){
 		return reFileNames;
	}
	protected String[] reFileNames = null;

	
   /**
	 * This method is used by the RartRunner to make resources, requested
	 * by the universe in getreFileNAmes available in the resourseObjects
	 * array. Note that the universe has to process the resource, in 
	 * particular, casting it to the actual resource (text, image etc).
	 * The requsted objects loaded in the order indicated by the reFileNames
	 * array. If the loading was unsucessful for any reason, the corresponding
	 * object has the value null.
	 *
	 * Note: The loading of the resources takes place after the execution of 
	 * the init method of universe. This means that the processing of the 
	 * resource has to take place in the cycle method as a second initiation
	 * probably unrelated to any reset. See examples, in particular the Three
	 * Balls universe.
	 * 
	 * @param Object[] os	the requested resource objects loaded from the file 
	 *						reFileNames if successful, otherwise null
	 */
	public void setResourceObjects( Object[] os){
		resourceObjects = os;
		reFileNames =null;
	}
	protected Object[] resourceObjects = null;

	// Section 5	Useful variables related to the execution of a universe
	// -------------------------------------------------------------------------
	/*
	 * The number of executions as public int nc, (nc is stepped
	 * after each cycle up to 2000000 when it is reset to avoid overflow).
	 * The size of the display window is available to the universe as 
	 * protected Dimension dimDisplay, and as the public xm, for width,
	 * and ym, for height.
	 * 
	 */
	 
	public static int nc;		// Set in the RartRunner. Used to vary the 
				// universe according to the number of cycles executed.
	public static boolean doubleBuffer=true; //set this false in your universe 
				// overriding this setting if you don't want double buffering.
	public static boolean needSound=false; //This variable set to true when a
				// universe needs a sound. Soundclip file reference has to be
				// provided in HTML startup. Only one sound in this realease.
	public static int debugLevel;	// Set by the RartRunner to the value of the 
				// parameter DEBUG_LEVEL provided as either a command-line 
				// parameter (for a RartRunner application) or as an HTML 
				// parameter (for a RartRunner applet). Override if necessary.
				
	/**
	 * The simplest way for the universe to get access to the resources of 
	 * the RartRunner is to provide the invoking RartRunner instance. This
	 * is done immidiately before the RartRunner initiates the universe 
	 * using the init of the Universe, which means that init has available 
	 * whatever the RartRunner can provide.
	 *
	 * Introduced in Nov 2001 to allow direct access to the awt peer of the
	 * RartRunner for the purpose of Image processiong.
	 *
	 * Since Nov 2001, 
	 */
	public final void setRartRunner(RR rr){
		rartrunner = rr;
		System.out.println("setRartRunner rartrunner "+rr);
	}

	protected RR rartrunner = null;
	 
	/**
	 * This method is used by the RartRunners to communicate the current size
	 * of the display, either as Dimension dimDisplay or the two variables xm, ym.
	 *
	 * @param Dimension d	the current size of the display
	 */
	public final void setExtents(Dimension d){ 
		xm=d.width;
		ym=d.height;
		if (dimDisplay.width == 0){
			 //dB= new Debug(); requires "private Debug dB;"
			 //dB.setLevel(2);
			 dimDisplay.width = xm;
			 dimDisplay.height = ym;			 
			 //dB.dbg( 2,"In Universe.setExtent(Initially):xm,ym "+xm+", "+ym );
		}else{			
			uParameter sizeUP = new uParameter(VIEWSIZE, "VIEWSIZE", xm, ym, 0);
			//dB.dbg( 2,"In Universe.setExtent(Running):xm,ym "+xm+", "+ym );
			manageChange(sizeUP);
		}
	}	// end setExtents
	protected Dimension dimDisplay = new Dimension(0,0);
	public static int xm,ym;	// Width and height of window; reset as needed 
			//by the RartRunner. uParameter, index VIEWSIZE, announces change.

	// Section 6	Methods related to security. 

	// The following methods should normally be of no concern to programmers of
	// a Rart universes.

	/**
 	 * Constructor with only function to avoid having more than one instantiation
	 * at a time.	Compare Finalizer Method
	 */ 
	 public Universe() throws InstantiationException{
		 if (true == instantiated)
			 throw new InstantiationException("A Universe exists alreay.");
		 instantiated = true;
		 System.out.println("Universe Version 1.4 instantiated");
	 }	 
	 private static boolean instantiated = false;
	  
	 	
	 public boolean equals(Object o)	{
		 return false;
	 }
	 	
	 protected Object clone()
		 throws CloneNotSupportedException{
		 throw new CloneNotSupportedException("A Universe exists already.");
	 }
	 
	 public void finalize(){
		 instantiated = false;
	 }
}  	// End of abstract class Universe