/** Copyright (c) 1995, 1996 Sun Microsystems, Inc. All
Rights Reserved.
** Extends Arthur van Hoff's animation template, to create an
animated
** checkerboard, using double buffering to eliminate image flashing
** and/or crawling.
**
** Modified to AnimatorApplet4 by John Pais, January 1998.
**/
Toggle your browser's Back
and Forward buttons to compare the
running applet to this code. |
Click here to run a fresh copy of the applet: AnimatorApplet4.html |
/** USE EXISTING JAVA CLASSES **/
import java.awt.*;
import java.applet.Applet;
/** EXTEND THE JAVA APPLET CLASS AND IMPLEMENT THE RUNNABLE INTERFACE
**/
public class AnimatorApplet4 extends Applet implements Runnable
{int frameNumber = -1;
int fps = 10;
// Define the default fps (frames per second)
int delay;
// as a global, in order to initialize in init()
Thread animatorThread;
// and control the frame-to-frame delay in run().
int delay;
Thread animatorThread;
boolean frozen = true;
Font font=new Font("TimesRoman",Font.BOLD,24);
String framestr;
int squareSize = 20;
// Define globals for the checkerboard square
boolean createTopSquareNextFrame = false;
// size, and the frame-to-frame top square.
Dimension preImageDim;
// Define preImage variables needed to
Image preImage;
// create the offscreen copy of the image
Graphics preImageGraphics;
// we want to paint on the screen.
/** INITIALIZE THE APPLET **/
public void init()
{setBackground(Color.red);
String str1, str2;
int fps = 10;
// Define the default fps (frames per second).
str1 = getParameter("fps");
// Possibly, get HTML string specifying the
try
// fps.
{if (str1 != null)
{fps =
Integer.parseInt(str1);} // If possible,
convert HTML fps to an
}
// integer.
catch (Exception e)
{}
// In case the try caused something strange.
str2 = getParameter("squareSize");
// Possibly, get HTML string specifying
try
// the squareSize.
{if (str2 != null)
{squareSize
= Integer.parseInt(str2);} // If possible, convert HTML squareSize
}
// to an integer.
catch (Exception e)
{}
// In case the try caused something strange.
}
Toggle your browser's Back
and Forward buttons to compare the
running applet to this code. |
Click here to run a fresh copy of the applet: AnimatorApplet4.html |
/** CLICK TO START OR STOP THE APPLET **/
public boolean mouseDown(Event e, int x, int y)
{if (frozen)
{frozen = false;
start();}
else
{frozen = true;
animatorThread = null;
// Instead of calling stop() here, since
}
// stop() now nullifies our preImage context,
return true;
// nullify only the animation thread in case
}
// we want to build on our current preImage.
/** GENERATE AND/OR START THE ANIMATION THREAD **/
public void start()
{if (frozen) { }
// The animation is supposed to stay frozen.
else
// Otherwise, generate and/or start the
{if (animatorThread
== null)
// animation thread. Apparently, if run
{animatorThread = new Thread(this);} // breaks after catching an
exception,
animatorThread.start();
// the animatorThread though not null
}
// will still need to be restarted.
}
Toggle your browser's Back
and Forward buttons to compare the
running applet to this code. |
Click here to run a fresh copy of the applet: AnimatorApplet4.html |
/** CREATE AND DISPLAY FRAMES OF THE ANIMATION THREAD
**/
public void run()
{Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
// Set the priority low.
long startTime = System.currentTimeMillis();
// Remember start time.
int delayLong = (fps
> 0) ? (10000/fps): 1000;
// Convert fps to milisecond
int delayShort = (fps
> 0) ? (1000/fps): 100;
// delay time between frames.
while (Thread.currentThread()
== animatorThread) // The animation
loop.
{frameNumber++;
// Advance the frame number.
framestr = "Frame " + frameNumber;
// Create the frame string.
repaint();
// Display the frame.
if (frameNumber != 0)
// Start with a longer delay
{delay = delayShort;}
// time for Frame 0, in order
else
// to avoid timing problems
{delay = delayLong;}
// when the thread starts up.
try
// Sleep for the delay period.
{startTime += delay;
Thread.sleep(Math.max(0,
startTime-System.currentTimeMillis()));
}
catch (InterruptedException e) {break;}
// In case the try caused
}
// something strange, exit
}
// the while loop.
/** CREATE THE CURRENT FRAME OF THE ANIMATION THREAD
**/
public void paint(Graphics g)
// This technique of painting by calling
{if (!frozen) update(g);}
// update, prevents the default (and hidden)
// behavior of update, and instead allows
public void update(Graphics g)
// the creation of an offscreen preImage
{Dimension d = size();
// before painting the screen.
boolean createTopSquare;
boolean fillSquare;
int frameShift;
int squareWidth, squareHeight;
int x = 0, y = 0;
int extendRow = 0;
if ((preImageGraphics == null)
||
(d.width
!= preImageDim.width) ||
// Compare the current applet
(d.height
!= preImageDim.height))
// viewing size to our preImage,
{preImageDim = d;
// and if different, resize our
preImage = createImage(d.width,d.height);
// next preImage.
preImageGraphics =
preImage.getGraphics();
}
preImageGraphics.setColor(getBackground());
// Clear the previous preImage
preImageGraphics.fillRect(0,0,d.width,d.height);
// by filling with the current
preImageGraphics.setFont(font);
// background color (red),
preImageGraphics.setColor(Color.black);
// and then create the next
preImageGraphics.drawString(framestr,155,39);
// offscreen preImage.
Toggle your browser's Back
and Forward buttons to compare the
running applet to this code. |
Click here to run a fresh copy of the applet: AnimatorApplet4.html |
/* Create the current checkerboard for
the current frame. This is done by
starting with
the red background and then moving down the columns of the
checkerboard
(starting with the leftmost column), deciding whether or
not to paint
a black square on top of the red background which creates
the checkerboard
effect. Frame 0 begins by skipping a red square at the
top of the leftmost
column, then paints a black one below it, skips a
red square below
it, paints a black one below it, etc. Frame 1 begins
its leftmost
column with a black square one pixel wide, frame 2 with
a black square
2 pixels wide, etc. These frames are then displayed in
sequence, creating
the checkerboard moving to the right effect.
*/
/* Set up the current frame and remember
appropriately for the next frame */
createTopSquare = createTopSquareNextFrame;
// Create top square: true/false?
frameShift = frameNumber % squareSize;
// Compute the frameShift, which is
// a number from 0 to squareSize-1.
if (frameShift == 0)
// frameShift equals the remainder
{squareWidth = squareSize;
// after dividing frameNumber by
createTopSquareNextFrame
= !createTopSquare; // squareSize. So, % is
}
// the mod operation.
else
{squareWidth = frameShift;
// Start the top of the leftmost
createTopSquareNextFrame
= createTopSquare; // column with a partial square--
}
// a rectangle of width frameShift
// (pixels).
fillSquare = createTopSquare;
// Fill or don't fill the leftmost
// top (partial) square of the current
// frame, depending on the value of the
// global variable createTopSquare.
Toggle your browser's Back
and Forward buttons to compare the
running applet to this code. |
Click here to run a fresh copy of the applet: AnimatorApplet4.html |
/* Begin the checkerboard for
the current frame */
while (x < d.width)
// Begin drawing the first row, but
{int extendColumn
= 0;
// proceed down each column from top
while
(y < d.height)
// to bottom, starting from the left.
{extendColumn += squareSize;
if (extendColumn <= d.height)
// Test column extension.
{squareHeight = squareSize;}
else
// If a full square won't fit at the
{squareHeight = d.height - y;}
// bottom of the column, then reduce
if (fillSquare)
// its height.
{preImageGraphics.fillRect(x, y, squareWidth, squareHeight);
fillSquare = false;
}
else
{fillSquare = true;}
y += squareHeight;
// Increment y.
}
// End of while y loop.
x += squareWidth;
// Increment x.
y = 0;
// Start at the top of the next
extendRow += squareWidth;
// column.
if (extendRow <= d.width)
// Test row extension.
{squareWidth = squareSize;}
else
// If a full square won't fit at the
{squareWidth = d.width - x;}
// far right, then reduce its width.
createTopSquare = !createTopSquare;
// Set up to do the opposite at the
fillSquare = createTopSquare;
// top of the next column.
}
// End of while x loop.
// Offscreen preImage now completed.
g.drawImage(preImage,0,0,this);
// Paint preImage on the screen.
}
Toggle your browser's Back
and Forward buttons to compare the
running applet to this code. |
Click here to run a fresh copy of the applet: AnimatorApplet4.html |
/** STOP THE ANIMATION THREAD **/
public void stop()
{animatorThread = null;
// The user either clicked to stop or left the page,
preImageGraphics = null;
// so wipe out the current thread and preImage context.
preImage = null;
}
}