![]() |
![]() |
We start by discussing threads, and the universal animation loop.
Here they are, in combined action.
frilled.cs.indiana.edu%pwd /nfs/grouchy/home/user2/www/classes/a348-dger/t540/lectures/two frilled.cs.indiana.edu%ls -ld Broad* Three* -rw-r--r-- 1 dgerman 2169 Nov 4 16:37 Broadway.java -rw-r--r-- 1 dgerman 503 Nov 4 17:01 Three.html frilled.cs.indiana.edu%cat Three.html <html> <title> Using Objects for Animation </title> <body bgcolor=white> <p> This animation lasts forever. When you're done looking at it simply go back to the page you came from. Your browser will know to stop the applet when you leave this page. Please notice the flicker... <p> <applet code="Broadway.class" width=300 height=300> </applet> <p> <em>Broadway Boogie Woogie</em>, dedicated to Piet Mondrian. </body> </html> frilled.cs.indiana.edu%cat Broadway.java import java.applet.*; import java.awt.*; public class Broadway extends Applet implements Runnable { Thread animation; int locx,locy; // location of rectangle int width, height; // dimensions of rectangle 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 the rect is in (up, down, left, right) static final int REFRESH_RATE = 100; // length of pausing interval (in ms) public void init() { System.out.println("Initializing... "); setBackground(Color.black); locx = 80; locy = 100; width = 110; height = 90; state = UP; } public void start() { System.out.println("Starting... "); animation = new Thread(this); // see run() below... if (animation != null) { animation.start(); } } public void paint(Graphics g) { System.out.println("Painting... "); g.setColor(Color.yellow); g.fillRect(0,0,90,90); g.fillRect(250,0,40,190); g.fillRect(80,110,100,20); // hidden rectangle g.setColor(Color.blue); g.fillRect(80,200,220,90); g.fillRect(100,10,90,80); g.setColor(Color.lightGray); g.fillRect(locx,locy,width,height); g.setColor(Color.red); g.fillRect(200,0,45,45); g.fillRect(0,100,70,200); g.setColor(Color.magenta); g.fillRect(200,55,60,135); } void updateRectangle() { switch (state) { case DOWN: locy += 2; if (locy >= 110) { state = UP; } break; case UP: locy -= 2; if (locy <= 90) { state = RIGHT; } break; case RIGHT: locx += 2; if (locx >= 90) { state = LEFT; } break; case LEFT: locx -= 2; if (locx <= 70) { state = DOWN; } break; } } public void run() { while (true) { repaint(); updateRectangle(); try { Thread.sleep (REFRESH_RATE); } catch (Exception e) { }; } } public void stop() { System.out.println("Stopping... "); if (animation != null) { animation.stop(); animation = null; } } } frilled.cs.indiana.edu%javac Broad*.java Note: Broadway.java uses or overrides a deprecated API. Note: Recompile with -deprecation for details. frilled.cs.indiana.edu%ls -ld Broad* -rw------- 1 dgerman 2173 Nov 4 17:02 Broadway.class -rw-r--r-- 1 dgerman 2169 Nov 4 16:37 Broadway.java frilled.cs.indiana.edu%
To eliminate the flicker we apply double-buffering.
frilled.cs.indiana.edu%pwd /nfs/grouchy/home/user2/www/classes/a348-dger/t540/lectures/two frilled.cs.indiana.edu%ls -ld Four* Broad*DB.java -rw-r--r-- 1 dgerman 2593 Nov 4 17:20 BroadwayDB.java -rw-r--r-- 1 dgerman 352 Nov 4 17:19 Four.html frilled.cs.indiana.edu%cat Four.html <html> <head><title>A Better Boogie Woogie</title></head> <body bgcolor="white"> This is the animation from before, with double buffering. No flicker... <p> <applet code="BroadwayDB.class" width=300 height=300> </applet> <p> <em>A Better Boogie Woogie</em>, also dedicated to Piet Mondrian <p> </body> </html> frilled.cs.indiana.edu%cat Broad*DB.java import java.applet.*; import java.awt.*; // double buffered and clipped public class BroadwayDB extends Applet implements Runnable { Thread animation; int locx,locy; // location of rectangle int width, height; // dimensions of rectangle static final byte UP = 0; // direction of motion static final byte DOWN = 1; static final byte LEFT = 2; static final byte RIGHT = 3; Graphics offscreen; Image image; byte state; // state the rect is in (same as before) static final int REFRESH_RATE = 100; // (that is, in ms) public void init() { System.out.println("Initializing... "); setBackground(Color.black); locx = 80; locy = 100; width = 110; height = 90; state = UP; image = createImage(300,300); offscreen = image.getGraphics(); } public void start() { System.out.println("Starting... "); animation = new Thread(this); if (animation != null) { animation.start(); } } public void update(Graphics g) { // this is new... g.clipRect(70,90,130,110); paint(g); } public void paint(Graphics g) { System.out.println("Painting... "); offscreen.setColor(Color.black); offscreen.fillRect(0,0,300,300); // clear buffer offscreen.setColor(Color.yellow); offscreen.fillRect(0,0,90,90); offscreen.fillRect(250,0,40,190); offscreen.fillRect(80,110,100,20); offscreen.setColor(Color.blue); offscreen.fillRect(80,200,220,90); offscreen.fillRect(100,10,90,80); offscreen.setColor(Color.lightGray); offscreen.fillRect(locx,locy,width,height); offscreen.setColor(Color.red); offscreen.fillRect(200,0,45,45); offscreen.fillRect(0,100,70,200); offscreen.setColor(Color.magenta); offscreen.fillRect(200,55,60,135); g.drawImage(image,0,0,this); } void updateRectangle() { switch (state) { case DOWN: locy += 2; if (locy >= 110) { state = UP; } break; case UP: locy -= 2; if (locy <= 90) { state = RIGHT; } break; case RIGHT: locx += 2; if (locx >= 90) { state = LEFT; } break; case LEFT: locx -= 2; if (locx <= 70) { state = DOWN; } break; } } public void run() { while (true) { repaint(); updateRectangle(); try { Thread.sleep (REFRESH_RATE); } catch (Exception exc) { }; } } public void stop() { System.out.println("Stopping... "); if (animation != null) { animation.stop(); animation = null; } } } frilled.cs.indiana.edu%javac BroadwayDB.java Note: BroadwayDB.java uses or overrides a deprecated API. Note: Recompile with -deprecation for details. frilled.cs.indiana.edu%ls -ld Broad*DB.* -rw------- 1 dgerman 2702 Nov 4 17:21 BroadwayDB.class -rw-r--r-- 1 dgerman 2593 Nov 4 17:20 BroadwayDB.java -rw-r--r-- 1 dgerman 2667 Nov 4 17:15 BroadwayDB.java~ frilled.cs.indiana.edu%
Let's now redesign the interior of the applet.
frilled.cs.indiana.edu%pwd /nfs/grouchy/home/user2/www/classes/a348-dger/t540/lectures/two frilled.cs.indiana.edu%ls -ld Five.html Chicago.java -rw-r--r-- 1 dgerman 1757 Nov 4 18:20 Chicago.java -rw-r--r-- 1 dgerman 347 Nov 4 18:30 Five.html frilled.cs.indiana.edu%cat Five.html <html> <head><title>An Object-Oriented Boogie</title></head> <body bgcolor=white> This is the same Mondrian of before, only the inside is different. <p> <applet code="Chicago.class" width=300 height=300> </applet> <p> Applet called Chicago, uses DancingRect, a standing still dancer. <p> </body> </html> frilled.cs.indiana.edu%cat Chicago.java import java.applet.*; import java.awt.*; // An Object-Oriented Boogie. public class Chicago extends Applet { static final int NUM_RECTS = 9; DancingRect r[]; // defined below public void init() { System.out.println("Initializing... "); setBackground(Color.black); initRectangles(); } public void initRectangles() { // allocate dancing rectangles r = new DancingRect[NUM_RECTS]; r[0] = new DancingRect(0,0,90,90,Color.yellow); r[1] = new DancingRect(250,0,40,190,Color.yellow); r[2] = new DancingRect(200,55,60,135,Color.yellow); r[3] = new DancingRect(80,200,220,90,Color.blue); r[4] = new DancingRect(100,10,90,80,Color.blue); r[5] = new DancingRect(80,100,110,90,Color.lightGray); r[6] = new DancingRect(200,0,45,45,Color.red); r[7] = new DancingRect(0,100,70,200,Color.red); r[8] = new DancingRect(200,55,60,135,Color.magenta); } public void start() { System.out.println("Starting... "); } public void paint(Graphics g) { for (int i=0; i<NUM_RECTS; i++) { r[i].paint(g); // paint each rectangle } } public void stop() { System.out.println("Stopping... "); } } class DancingRect { int locx, locy; // (locx,locyy) are coordinates of upper left corner of rectangle int width, height; // width and height of rectangle Color myColor; // color of rectangle public DancingRect(int x,int y,int w,int h,Color c) { locx = x; locy = y; width = w; height = h; myColor = c; } public void danceStep() { // does nothing } public void paint(Graphics g) { g.setColor(myColor); g.fillRect(locx,locy,width,height); } } frilled.cs.indiana.edu%javac Chicago.java frilled.cs.indiana.edu%ls -ld Dan* Chi* Fiv* -rw-r--r-- 1 dgerman 1396 Nov 4 18:32 Chicago.class -rw-r--r-- 1 dgerman 1757 Nov 4 18:20 Chicago.java -rw------- 1 dgerman 679 Nov 4 18:32 DancingRect.class -rw-r--r-- 1 dgerman 347 Nov 4 18:30 Five.html frilled.cs.indiana.edu%
What follows is an exercise in another one of the fundamental aspects of Java.
We take a look at dynamic method binding. First, we add a few more classes.
Indeed, we have takenfrilled.cs.indiana.edu%pwd /nfs/grouchy/home/user2/www/classes/a348-dger/t540/lectures/two frilled.cs.indiana.edu%ls -ld *.java -rw------- 1 dgerman 1225 Nov 4 19:09 BoogieRect.java -rw-r--r-- 1 dgerman 2169 Nov 4 16:37 Broadway.java -rw-r--r-- 1 dgerman 2593 Nov 4 17:20 BroadwayDB.java -rw-r--r-- 1 dgerman 1215 Nov 4 19:09 Chicago.java -rw------- 1 dgerman 563 Nov 4 19:09 DancingRect.java -rw------- 1 dgerman 2211 Nov 4 19:10 Simphony.java -rw------- 1 dgerman 981 Nov 4 19:09 WaltzRect.java frilled.cs.indiana.edu%
DancingRect
out of the Chicago
source code, to
keep each thing into its own.
That was one new class, with its ownfrilled.cs.indiana.edu%cat BoogieRect.java import java.awt.*; class BoogieRect extends DancingRect { // BoogieRect inherits all instance variables and // methods from DancingRect 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 BoogieRect(int x,int y,int w,int h,Color c) { super(x,y,w,h,c); // call superclass constructor max_x = locx + 13; min_x = locx - 13; max_y = locy + 13; min_y = locy - 13; } // override danceStep() public void danceStep() { switch (state) { case DOWN: locy += 2; if (locy >= max_y) { state = UP; } break; case UP: locy -= 2; if (locy <= min_y) { state = RIGHT; } break; case RIGHT: locx += 2; if (locx >= max_x) { state = LEFT; } break; case LEFT: locx -= 2; if (locx <= min_x) { state = DOWN; } break; } } } frilled.cs.indiana.edu%
danceStep
. Here's another class, taken directly from Strauss:
We now create a visual simphony, nothing less.frilled.cs.indiana.edu%cat WaltzRect.java import java.awt.*; class WaltzRect extends DancingRect { 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 point of the waltz int right_x; // the x coordinate of right point of the waltz int left_x; // the x coordinate of left point of the waltz public WaltzRect(int x,int y,int w,int h,Color c) { super(x,y,w,h,c); // call superclass constructor bottom_x = locx + 17; right_x = bottom_x + 17; left_x = locx; } // override danceStep() public void danceStep() { switch (state) { case SE: locx++; locy++; if (locx == bottom_x) { state = NE; } break; case NE: locx++; locy--; if (locx == right_x) { state = W; } break; case W: locx-- ; if (locx == left_x) { state = SE; } break; } } } frilled.cs.indiana.edu%
The picture look like that:
So here's the source code for the applet that puts everything together.
Andfrilled.cs.indiana.edu%cat Simphony.java import java.applet.*; import java.awt.*; public class Simphony extends Applet implements Runnable { Thread animation; Graphics offscreen; Image image; static final int NUM_RECTS = 9; // in milliseconds static final int REFRESH_RATE = 100; // in milliseconds DancingRect r[]; public void init() { System.out.println("Initializing... "); setBackground(Color.black); initRectangles(); image = createImage(bounds().width,bounds().height); offscreen = image.getGraphics(); } public void initRectangles() { // allocate dancing rectangles r = new DancingRect[NUM_RECTS]; r[0] = new DancingRect(0,0,90,90,Color.yellow); r[1] = new BoogieRect(250,0,40,190,Color.yellow); r[2] = new WaltzRect(200,55,60,135,Color.yellow); r[3] = new BoogieRect(80,200,220,90,Color.blue); r[4] = new WaltzRect(100,10,90,80,Color.blue); r[5] = new BoogieRect(80,100,110,90,Color.lightGray); r[6] = new WaltzRect(200,0,45,45,Color.red); r[7] = new WaltzRect(0,100,70,200,Color.red); r[8] = new BoogieRect(200,55,60,135,Color.magenta); } public void start() { System.out.println("Starting... "); animation = new Thread(this); if (animation != null) { animation.start(); } } // update each rectangle's position. // DYNAMIC METHOD BINDING OCCURS HERE! public void updateRectangles() { for (int i=0; i<NUM_RECTS; i++) { r[i].danceStep(); // each rectangles dance step } } // 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_RECTS; i++) { r[i].paint(offscreen); // paint each rectangle } g.drawImage(image,0,0,this); } public void run() { while (true) { repaint(); updateRectangles(); try { Thread.sleep (REFRESH_RATE); } catch (Exception exc) { }; } } public void stop() { System.out.println("Stopping... "); if (animation != null) { animation.stop(); animation = null; } } } frilled.cs.indiana.edu%cat Six.html <html> <head><title>A Visual Simphony, Nothing Less... </title></head> <body bgcolor=white> <p>A Visual Simphony, Nothing Else... <p> <applet code="Simphony.class" width=300 height=300> </applet> <p>Dedicated to Piet Mondrian and Victor Borge. <p> </body> </html> frilled.cs.indiana.edu%javac Simphony.java Note: Simphony.java uses or overrides a deprecated API. Note: Recompile with -deprecation for details. frilled.cs.indiana.edu%ls -ld *.class -rw-r--r-- 1 dgerman 837 Nov 4 19:10 BoogieRect.class -rw-r--r-- 1 dgerman 2173 Nov 4 17:02 Broadway.class -rw-r--r-- 1 dgerman 2702 Nov 4 17:21 BroadwayDB.class -rw-r--r-- 1 dgerman 1398 Nov 4 19:10 Chicago.class -rw-r--r-- 1 dgerman 683 Nov 4 19:10 DancingRect.class -rw-r--r-- 1 dgerman 2620 Nov 4 19:25 Simphony.class -rw-r--r-- 1 dgerman 746 Nov 4 19:10 WaltzRect.class frilled.cs.indiana.edu%