Java-aware browsers show
a moving twister.

Anatomy of an Animation

by M. Gallant 6/12/97

The twister Java applet portrays a twister meandering slowly across a pastoral scene with random shaped and timed lightning strikes in the background. Threatening background sky flicker adds to the atmosphere as well as debris tossed up by the twister's tip. The animation consists of 5 elements:

The applet implements the Runnable interface for the animation to run in a thread. Four color instance variables are defined:

Applet instance variables xtor, ytor are the instantaneous position coordinates of the upper-left corner of the tornado image component relative to the upper left corner of the applet frame. Similarly, xlight, ylight are the starting coordinates of the lightning streak. The applet requires 5 gif images to be loaded, 4 variations of the twister image (tor0.gif, tor1.gif...) and the background landscape (hillst.gif) as declared in the init() method.


init() method

The init method is called as soon as the applet has loaded but before the actual thread starts with the start() method. init() defines several instance variables and sets up memory for double-buffering graphics with the offIm and offGr objects. The MediaTracker object tracker is then defined and used to "register" all the image components needed in the animation. The 4 images of the twister are also assigned to the array tor[i] which however does not force the images to network load yet.

run() method

Control of the animation is contained in the run() method which starts after the init() method completes. The images are loaded here and then the infinite loop starts with while (true) {. The boolean variable lightning is randomly set to true about every 20 times through the loop, and determines if a lightning strike is to be drawn in the paint() method. The next loop moves the twister smoothly horizontally and vertically via a slow sine wave and runs through the 4 twister images, with the current twister image to paint specified by curIm. The repaint() method is then called which in turn calls the update() method which is overridden to call the paint() method writing the image to the screen via double-buffering. Note that lightning is held true for the 4 twister images, providing greater image persistence of the lightning following which lightning is set false.

paint() method

The rendering of each frame of the animation is specified in the paint() method. The first conditional test:

if ((tracker.statusID(0, false) == MediaTracker.COMPLETE)&&(curIm!=null))

enables graphics updating only if all images have been (network) loaded as monitored by the MediaTracker object tracker failing which only the background color of the applet is drawn. To prevent screen flicker, double-buffering is used (with offIm and offGr being the memory image and graphics context respectively). The sequence of image formation is:

As always, experimentation with animations is often effective. Frequently, very surprising and pleasing visual results are obtained by trial and error. For more complicated animations, it is better to define separate threads for processes that are considered independent events. Otherwise, the code becomes too complex with tests, polling etc. Above all,