© 2000-2003 A-Square, Inc. Cambridge, MA
>
/*
* @Planes4d 1.0 030115
*
* © A-Square, Inc.
* 175 Richdale Ave, Cambridge MA 02140
*/
import rrlet.*;
import rartbase.*;
import java.awt.*;
import java.lang.*;
/**
* 'Planes rotating
*
* This Program is one in the Rart®, or Random Art, series of programs
* that generate ever changing pictures. Simple geometries and random
* dynamics create visual effects that may be pleasing to the eye.
* It uses the Plane class for objects, the planes, that fill the screen.
*
* In EX4c We show how to write a new universe
*
* @version 1.0d 030115
*
* @author Jan Aminoff
*/
public final class Planes4d extends Universe {
// Section 1 Identifying the Universe
// ------------------------------------------------------------------------
public String getName() // Name,
{return("Planes, in Exercise 4b");} // no more than 20 letters.
public String getDescription()
{return(sd);} // Description,
// no more than 350 letters describing the universe. Will
// be displayed in up to five lines of about 70 characters.
private String sd=" We shall see how we progressively can add features "+
"to a new universe to make it more visually interesting. "+
"The first version, EX4c, just offers black planes.";
public String getRartist() // Rartist,
{return("Jan Aminoff 2003");} // no more than 24 characters.
// Section 2 What the universe does
// ------------------------------------------------------------------------
// About colors - constants and defaults
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 };
private int bc=0; // default number of color for background (black )
private int pc=1; // default number of color for foreground (blue )
private Color background = colors[bc];
private boolean resetscreen=false; // Signal to recolor background
// Other variables
private int nnmax = 20; // maximum number of Planes, set in reset
private int nn=5; // actual number of Planes, set as number.getCur()
private Plane planearray[]=new Plane[nnmax]; // Up to 30 Planes.
private int vv = 5; // Current roteation speed in degrees per second
private Debug dB; // used when debugging, especially as dB.dbg(n, string)
// The method init() is prescribed by Universe
public void init(){
dB= new Debug();
dB.setLevel(2); // Set level to 1 or 2 for tracing outputs.
setParams(); // See Section 3.
reset(); // See below.
}
private void reset(){
/** Reset is used in init and also in manageChange when restarting
* the universe after change of some parameters.
*/
// Initialize Planearray
nn=number.getCur(); // Have to use possibly modified parameters.
vv= speed.getCur(); // Max rotation speed in degrees per second
int vc = vv*ct.getCur(); // Max rot in degrees per 1000 cycles
pc=pcolor.getCur(); // Index to colors array.
dB.dbg( 1 ,"In Planes.reset, xm: "+xm+", ym: "+ym);
dB.dbg( 1 ,"In Planes.reset, planecolor is "+colornames[pc]);
for (int i=0; i < nn; i++) {
planearray[i] = new Plane(xm, ym, vc, pc);
planearray[i].setFi(RND(360));
}
// Set background
bc=bcolor.getCur();
background = colors[bc];
} // end reset
// This method is prescribed by Universe
public Color getBackground(){return background;}
// The following three variables are important in cycle.
private int m; // Index to current waxing or waning egg.
private int status; // See Plane for the significance of status.
// This method is prescribed by Universe. Everything interesting happens
// in the cycle method which is called periodically by the RartRunner
public void cycle ( Graphics g){
/** In init, nn Planes have been initiated in planearray. The planes rotate
* clockvisw and counterclockvise for a total of 360 degrees, when it will
* be replaced with a new plane.
*/
// Reset screen always
g.setColor(background);
g.fillRect(0,0,xm,ym);
// We go through all planes
nn = number.getCur();
for (int i=0; i<nn; i++){
Plane p1=planearray[i]; // Current Plane.
status = p1.drawChange(g);
if (status == p1.DONE){ // If plane rotated 360 degrees,
// put a new Plane in Planearray,
planearray[i]= new Plane(xm, ym, vv*ct.getCur(), pc);
dB.dbg( 1 ,"In Planes,cycle, new Plane for index i: "+i);
}
}
} // end of cycle(g)
// Section 3 uParameters as used in the universe
// ------------------------------------------------------------------------
// number of Planes
private uParameter number; //Number of Planes - PARAMETER
private int nnmin=1; // nnmax and nn are given values before init
private String ndescr=
"This parameter indicates the maximum number of 'Planes'"+
"visible at any one time. ";
// maximum speed of an Plane
private uParameter speed; // speed of rotation - PARAMETER
private int v=2,vmax=5,vmin=1;
private String sdescr=
"The parameter actually determines the maximum rate of rotation"+
"of all Planes. It is here given in degrees per second.";
// cycletime
private uParameter ct; // Cycletime - PARAMETER
// Detailes of the ct parameter can be seen in Universe
// Plane color
private uParameter pcolor; // Plane Color - PARAMETER
private uParameter bcolor; // Background Color - PARAMETER
private String cdescr=
"Plane color and Background colors may be chosen from "+
"the 13 primary colors offered by Java. ";
static String colornames[]=
{" black "," blue "," cyan"," dark grey "," grey ",
" green "," light grey "," magenta "," orange ",
" pink "," red "," white "," yellow "};
private void setParams(){
number= new uParameter
(NUMBER,"Number of Planes",nnmin,nn,nnmax,ndescr);
//The adduParameter() method is defined in Universe.
adduParameter(number);
speed=new uParameter(PARA4,"Rotation Speed",vmin,v, vmax, sdescr);
adduParameter(speed);
ct= new uParameter
(CYCLETIME,"Cycle Time", 20,100,200, CycleTimeDescr);
// Since "Cycle Time" is a compulsory parameter, Universe
// provides the description CycleTimeDescr.
adduParameter(ct);
// The color parameters pcolor and bcolor have the same description
// and array, colornames, for selection.
pcolor= new uParameter(PARA5,"Plane Color",pc,colornames, cdescr);
adduParameter(pcolor);
bcolor= new uParameter(PARA6,"Background Color",bc,colornames, cdescr);
adduParameter(bcolor);
} //end setParams()
// This method is prescribed by universe. Its purpose is to deal with any
// changes in parameters by the user.
public void manageChange(uParameter uP){
/** This method is called by the RartRunner when a user has modified any
* of the parameters. The new information is conveyed in a uParameter.
* In the case of Planes, we have elected to restart the universe for any
* changes even if for some parameters it would not be strictly neccesary.
*/
int idx=uP.getIndex();
dB.dbg( 2,"In Planes, Change in : "+uP.getName());
if (uPs[idx]!=null) uPs[idx]=uP; // ensures that uPs, the array of
// current parameters is up to date
switch (idx){
case VIEWSIZE:
reset(); // Cange in windowsize, just restart.
break;
case NUMBER:
number=uP; // A more sophisticated program could handle
reset(); // changes in the maximum number of Planes,
break; // but this is simpler!
case PARA4: // used for speed of rotation
speed=uP;
reset(); // simple solution.
break;
case PARA5: // used for for Plane color
pcolor=uP;
reset(); // No alternative to restart here.
dB.dbg(1,"Planecolor is now "+colornames[pc]);
break;
case PARA6: // used for Background color
bcolor=uP;
reset(); // No alternative to restart here.
dB.dbg(1,"Background is now "+colornames[bc]);
break;
}
} // end of manageChange()
// Sections 4, and 5 in Universe have no corresponding entries in the
// Planes universe.
// Section 6 Methods related to security.
// -----------------------------------------------------------------------
// The following constructor invokes the Universe constructor which is
// programmed to throw an exception in order to avoid multiple
// instantiations by mistake or bad intent.
public Planes4d( ) throws InstantiationException
{ }
} // end of Planes class
>
>
/*
* @Plane 1.0d 030115
*
* © A-Square, Inc.
* 175 Richdale Ave, Cambridge MA 02140
*/
import java.awt.*;
import java.lang.*;
import rartbase.*;
//import java.lang.math; // for sin, cos and pi
public class Plane{
/** --------------------------------------------------------------------------
* The Plane is a rectangle which rotates around a vertical axis at some speed.
* The effect of rotation is achieved through the modification of the color
* which changes as the angle of the light, which is thought to come from an
* infinitely distant source behind the right the observer, at 45 degrees to
* the plane of the screen.
*
* @version 1.0d 030115
* Used in Exercise 4d in the Introduction to Java tutorial.
*
* @author Jan Aminoff
*/
private int x; // x pos of center of oval
private int y; // y pos of center of oval
private static int xys = 40; // minimum space between center and edge of window
private int dir; // dir = 1 for positive rotation, -1 for negative
private float dv; // Speed degrees/cycle set as dir*(1.0+RND(speed))/1000;
private float ffi; // Floating point repr of fi
private int fi; // Angle from plane of screen in degrees.
private int rr; // half max size of plane
private int hh; // half height of plane
private int nc = 0;
public int status;
public static final int INITIALIZED=1;
public static final int ROTATING1=2;
public static final int ROTATING2=3;
public static final int DONE=4;
private static int RND(int x){
return(Universe.RND(x));
}
// About colors - constants and defaults
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 };
private int colorindex;
static int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, //11
41, 43, 43,47, 53, 59, 61, 67, 71, 73, //10
47, 83, 83}; //3
private Debug dB; // used when debugging, especially as dB.dbg(n, string)
// constructor
/**
* Constructor for a Plane, rotating around its middle vertical axis
* @param xmax Width of present screen in pixels
* @param ymax Height of screen in pixels
* @param speed Speed of rotation in degrees per 1000 cycles
* @param c Basic color of plane, index to color array
*/
public Plane(int xmax, int ymax, int speed, int c) {
// We may need Debug to develop this universe
dB= new Debug();
int debuglevel=2; // Set level to 1 or 2 for tracing outputs.
dB.setLevel(debuglevel);
// Center of plane is more than xys away from edge
x = xys+RND(xmax-xys);
y = xys+RND(ymax-xys);
status = INITIALIZED;
colorindex = c;
// Note that dx and dy are selected independently from the primes array.
// Causes great variation in the configurations.
hh = (primes[2+RND(13)]*ymax)/200; // max size 40% of window height
rr = (primes[3+RND(21)]*xmax)/200; // max size 80% of window width
fi = 90; //Angle to plane of screen, Starts perpedicular
dir = 2*RND(2)-1; // 1 or -1, that is clockwise or counterclocwise
dv = (float)(dir*((2.0+RND(speed))/100)); // Increment angle per cycle
//dB.dbg(1, "Plane.Plane dv "+dv);
// dB.dbg(1,"Debug activated at level "+debuglevel);
} // End of Plane constructor
public void setFi( int phi){ // new for version d
fi = (phi < 0)? - phi%360:phi%360 ;
}
public int drawChange(Graphics g){
/** The drawChange method provides the functionality of the planes class.
* It redraws the plane after a rotation of nc*dv degrees .
* It returns its status which relates to the number of complete rotations
* passing the plane perpendicular to the screen.
*/
int newstatus=status;
switch(status){
case INITIALIZED:
newstatus = ROTATING1;
ffi = fi;
case ROTATING1:
case ROTATING2:
drawPlane(g);
ffi += dv;
// dB.dbg(1,"Plane.drawChange x "+x+", ffi "+ffi);
fi= (int)(ffi) ;
// Make sure fi in interval 0 - 360
int fi1= (ffi < 0.0)? 360:(ffi>360.0)? 0:fi;
if (fi != fi1){
fi = fi1;
ffi = fi;
newstatus = ROTATING2;
}
if ((status == ROTATING2) && (((dv>0)&& (ffi>90))||((dv<0)&&(ffi<90))))
newstatus = DONE;
break;
}
status = newstatus;
return (status);
} // end DrawChange
private void drawPlane( Graphics g){
/*
* Draws the plane
* Width is rr*COS(fi), Height is constant hh
* First determine the color
* Our strategy must be to consider the thirteen colors separately, and for
* each color consider how the tree components move. See shadedColor.
*
* In Plane4d, we only consider light as coming from straight behind the
* observer. When fi goes from 90 to 0 or 180, the color of the plane
* goes from 80% to white. We call the angle psi. Here psi = 90-fi and the
* sat can be calculated as 20.0+80.0*cos(abs(psi))
*/
int idx = colorindex;
int psi = (fi>180)?90- fi+180: 90-fi;
double alpha = Math.abs(psi)*Math.PI / 180;
// ecial case for white, idx = 11
int sat = (int)(((idx == 11)? 100.0:50.0)*Math.sin(alpha));
g.setColor(shadedColor(idx, sat));
alpha = ffi * Math.PI / 180.0 ;
int r = Math.abs( (int) (rr*Math.cos(alpha)));
// dB.dbg(1, "Plane.drawPlane Width="+2*r+" Height="+hh+ " fi="+fi);
g.fillRect(x-r, y-hh, 2*r, 2*hh);
} // end drawPlane
/**
* Produces a color that is linearly changed from original basic Java
* color to white.
* @ idx index to one of 13 Java colors
* @ sat measure of saturation (?) percent from 0 to 100
*/
private Color shadedColor( int idx, int sat){ // New for 4d
int dig, dig1; //Digits of Color
Color c1; // Resulting color
switch(idx){
case 0: // Black Shades of Grey treated the dame
case 3: // Dark Grey
case 4: // Light gray
case 6: // Grey
dig=(int)(sat*255.0/100);
c1= new Color(dig,dig,dig);
break;
case 1: // Blue
dig = (int)(sat*255.0/100);
c1= new Color(dig,dig,255);
break;
case 2: // Cyan
dig = (int)(127.0+sat*128.0/100);
c1 = new Color(dig,255,255);
break;
case 5: // Green
dig = (int)(127.0+sat*128.0/100);
c1 = new Color(dig,255,dig);
break;
case 7: // Magenta
dig = (int)(127.0+sat*128.0/100);
c1 = new Color(255,dig,255);
break;
case 8: // Orange
dig = (int)(127.0+sat*128.0/100);
dig1 = (int)(sat*255.0/100);
c1 = new Color(255,dig,dig1);
break;
case 9: // Pink
dig = (int)(163.0+sat*93.0/100);
c1 = new Color(255,dig,dig);
break;
case 10: // Red
dig = (int)(sat*255.0/100);
c1 = new Color(255,dig,dig);
break;
case 11: // White - Shades from light grey to whitw
dig = (int)(163.0+sat*93.0/100);
c1 = new Color(dig,dig,dig);
break;
case 12: // Yellow
dig = (int)(sat*255.0/100);
c1 = new Color(255,255,dig);
break;
default:
dB.dbg(0,"Color " +idx + " not yet supported.");
c1 = null;
break;
}
return c1;
} // end shadedColor
} // end class Plane
>