July 31, 2005
Wow, that's it for July, huh? It's been a
hot month for weather and the consensus for global warming seems to
be, "yeah, but who controls the weather?"
The "Suggestion Box" that concludes BAJGP's
chapter 2 suggests continuously varying width, height and shape
(oval vs. rectangle) for the elements of Mondrian. This led me
to write the following variation on the code:
/**
* @(#)Mondrian5.java
* @version 1.00 05/07/31
*/
import java.applet.*;
import java.awt.*;
import java.util.Random;
public class Mondrian5
extends
Applet implements Runnable {
Thread animation;
Graphics offscreen;
Image image;
static final int NUM_SHAPES
= 9; // in ms
static final int
REFRESH_RATE = 100; // in ms
static final byte RECT = 0;
// direction of motion
static final byte OVAL = 1;
byte SHAPE_TYPE=0;
MovingShape shape[];
public void init() {
System.out.println(">>
init <<");
setBackground(Color.black);
initShapes();
image =
createImage(bounds().width,bounds().height);
offscreen =
image.getGraphics();
}
public void initShapes() {
// allocate Moving shapes' memories and
positions
shape = new
MovingShape[NUM_SHAPES];
shape[0] =
new
MovingShape(0,0,90,90,RECT,Color.yellow);
shape[1] =
new
BoogieShape(250,0,40,190,OVAL,Color.yellow);
shape[2] =
new
WaltzShape(200,55,60,135,RECT,Color.yellow);
shape[3] =
new
HurkyShape(80,200,220,90,OVAL,Color.blue);
shape[4] =
new
WaltzShape(100,10,90,80,RECT,Color.blue);
shape[5] =
new
BoogieShape(80,100,110,90,OVAL,Color.lightGray);
shape[6] =
new
WaltzShape(200,0,45,45,RECT,Color.red);
shape[7] =
new
HurkyShape(0,100,70,200,OVAL,Color.red);
shape[8] =
new
BoogieShape(200,55,60,135,RECT,Color.magenta);
}
public void start() {
System.out.println(">>
start <<");
animation =
new Thread(this);
if (animation !=
null) {
animation.start();
}
}
//
update each rectangle's position.
// DYNAMIC METHOD BINDING OCCURS HERE!
public void updateShapes() {
for (int
i=0; i<NUM_SHAPES; i++) {
shape[i].Movement(); // each rectangles
Movement
}
}
//
override update so it doesn't erase screen
public void update(Graphics
g) {
paint(g);
}
public void paint(Graphics
g) {
offscreen.setColor(Color.black);
offscreen.fillRect(0,0,300,300); // clear buffer
for (int
i=0; i<NUM_SHAPES; i++) {
shape[i].paint(offscreen); // paint each rectangle
}
g.drawImage(image,0,0,this);
}
public void run() {
while (true)
{
repaint();
updateShapes();
try
{
Thread.sleep (REFRESH_RATE);
}
catch (Exception
exc) { };
}
}
public void stop() {
System.out.println(">>
stop <<");
if (animation !=
null) {
animation.stop();
animation = null;
}
}
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
class MovingShape {
int ulCornx, ulCorny;
// (ulCornx,ulCornyy) are coordinates of
upper
// left corner of the shape
int width, height;
// width and height of shape
Color
shapeColor; // color of shape
byte ShapeType;
////constructor///////////////////////////////////////////////////
public MovingShape(int
x,int y,int
w,int h,byte
s,Color c) {
ulCornx = x;
ulCorny = y;
width = w;
height = h;
shapeColor = c;
ShapeType = s;
}
public void Movement() {
// does nothing except provide a
placeholder for dynamic binding
}
public void paint(Graphics
g) {
g.setColor(shapeColor);
if(ShapeType ==
0)
g.fillRect(ulCornx,ulCorny,width,height);
else
g.fillOval(ulCornx,ulCorny,width,height);
}
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
class BoogieShape
extends MovingShape {
//
BoogieShape inherits all instance variables and
// methods from MovingShape
static final byte UP = 0;
// direction of motion
static final byte DOWN = 1;
static final byte LEFT = 2;
static final byte RIGHT = 3;
byte state;
// state of rectangle
int max_x;
// max x value
int min_x;
// min x value
int max_y;
// max y value
int min_y;
// min y value
/////////////////////////////////////////////////////////////////
public BoogieShape(int
x,int y,int
w,int h,byte
s, Color c) {
super(x,y,w,h,s,c);
// call superclass constructor
max_x = ulCornx
+ 13;
min_x = ulCornx
- 13;
max_y = ulCorny
+ 13;
min_y = ulCorny
- 13;
}
//
override Movement()
public void Movement() {
switch (state) {
case
DOWN:
ulCorny += 2;
if (ulCorny >= max_y) {
state = UP;
}
width += 2;
break;
case
UP:
ulCorny -= 2;
if (ulCorny <= min_y) {
state = RIGHT;
}
width -= 2;
break;
case
RIGHT:
ulCornx += 2;
if (ulCornx >= max_x) {
state = LEFT;
}
height += 2;
break;
case
LEFT:
ulCornx -= 2;
if (ulCornx <= min_x) {
state = DOWN;
}
height -= 2;
break;
}
}
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// WaltzShape also inherits from MovingShape
class WaltzShape
extends MovingShape {
byte state;
static final byte SE = 0;
// going southeast
static final byte NE = 1;
// going northeast
static final byte W = 2;
// going west
int bottom_x;
// the x coordinate of
// bottom pt of the waltz
int right_x;
// the x coordinate of
// right pt of the waltz
int left_x;
// the x coordinate of
// left pt of the waltz
/////////////////////////////////////////////////////////////////
public WaltzShape(int
x,int y,int
w,int h,byte
s, Color c) {
super(x,y,w,h,s,c);
// call superclass constructor
bottom_x =
ulCornx + 17;
right_x =
bottom_x + 17;
left_x = ulCornx;
}
//
override Movement()
public void Movement() {
switch (state) {
case
SE:
ulCornx++;
ulCorny++;
if (ulCornx == bottom_x) {
state = NE;
}
break;
case
NE:
ulCornx++;
ulCorny--;
if (ulCornx == right_x) {
state = W;
}
break;
case
W:
ulCornx-- ;
if (ulCornx == left_x) {
state = SE;
}
break;
}
}
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
class HurkyShape
extends MovingShape {
Random r1 =
new Random();
//
HurkyRect inherits all instance variables and
// methods from MovingRect
static final byte UP = 0;
// direction of motion
static final byte DOWN = 1;
static final byte LEFT = 2;
static final byte RIGHT = 3;
byte state;
// state of rectangle
int max_x;
// max x value
int min_x;
// min x value
int max_y;
// max y value
int min_y;
// min y value
/////////////////////////////////////////////////////////////////
public HurkyShape(int
x,int y,int
w,int h,byte
s, Color c) {
super(x,y,w,h,s,c);
// call superclass constructor
max_x = ulCornx
+ 18;
min_x = ulCornx
- 12;
max_y = ulCorny
+ 18;
min_y = ulCorny
- 13;
}
//
override Movement()
public void Movement() {
int i =
r1.nextInt()%4;
int j =
r1.nextInt()%4;
switch (state) {
case DOWN:
ulCorny += i;
if (ulCorny
>= max_y) {
state = UP;
}
break;
case UP:
ulCorny -= i;
if (ulCorny
<= min_y) {
state = RIGHT;
}
break;
case RIGHT:
ulCornx += j;
if (ulCornx
>= max_x) {
state = LEFT;
}
break;
case LEFT:
ulCornx -= j;
if (ulCornx
<= min_x) {
state = DOWN;
}
break;
}
}
}
|