|
To access the contents, click the chapter and section titles.
Platinum Edition Using HTML 4, XML, and Java 1.2
Listing 39.16 Animation1.javaThis Applet Loads and Displays a Series of Images in Rapid Succession import java.awt.*; import java.applet.Applet; public class Animation1 extends Applet implements Runnable { int fFrame = -1; int fDelay; Thread fThread; Image[] fEarth; public void init() { fEarth = new Image[30]; String theString; int theFramesPerSecond = 10; //load in the images for (int i=1; i<=30; i++) { System.err.println(Starting load from + getCodeBase() + of ./Earth + i +.gif); fEarth[i-1] = getImage (getCodeBase(), ./Earth+i+.gif); } //How many milliseconds between frames? theString = getParameter(fps); try { if (theString != null) { theFramesPerSecond = Integer.parseInt(theString ); } } catch (NumberFormatException e) {} fDelay = (theFramesPerSecond > 0) ? (1000 / theFramesPerSecond) : 100; } public void start() { // start a new thread for the animation if (fThread == null) { fThread = new Thread(this); } fThread.start(); } public void stop() { // stop the animation thread fThread = null; } public void run() { // run at a low priority; animation is second-place to content Thread.currentThread().setPriority(Thread.MIN_PRIORITY); long theStartTime = System.currentTimeMillis(); //Here comes the show. while (Thread.currentThread() == fThread) { //Advance the frame. fFrame++; //Display it. repaint(); //Delay depending on how far we are behind. try { theStartTime += fDelay; Thread.sleep(Math.max(0, theStartTime- System.currentTimeMillis())); } catch (InterruptedException e) { break; } } } //Draw the current frame public void paint(Graphics g) { g.drawImage(fEarth[fFrame % 30], 0, 0, this); } } This applet works, but it suffers from two problems. First, the animation is far from smooth. Even when the images are loading from the local hard drive, we notice a certain jerkiness as the frames change. Second, if we load this applet over the network, the animation may begin before all the image files have finished loading, resulting in an ugly half-drawn frame. In the next two sections well solve both of these problems. Were going to use this applet as the basis for building a smooth, flicker-free animation applet. Well examine Animation1.java in detail. Youll notice that this applet implements an interface called Runnable.Runnable enables the applet to start a new thread of control so the animation can proceed independently of the user interface.
Our list of instance variables includes a reference to the animation thread (fThread) and a reference to the array of images. Were using 30 frames of the revolving Earth, so we call this array fEarth. In init() we loop from 1 to 30, loading the images of Earth. (Theyre stored in files named Earth1.gif through Earth30.gif.) Next, we look for an applet <PARAM> called fps (frames per second). If we find it, we attempt to parse it into a number. If we dont find it or if we cant read it, we use 10 frames per second as the basis for calculating the delay between calls to paint(). When the browser first shows the applet, it calls init() followed by start(). The browser will call stop() if the user iconifies the browser window or moves to a different page. We handle start() by checking to see whether the animation thread has already been set up. If it hasnt, we instantiate it. In either case, we start() the thread and destroy it in stop(). The required method of Runnable is run(). The Java runtime environment calls this method whenever time is available to run our thread. Our version of run() starts by setting the animation threads priority to a low value because any user interaction should take precedence over the animation. Then we simply step through the frames, repaint on each loop, and delay as necessary to match the desired frame rate. Finally, the work is done in paint() itself (as it is in most graphics-intensive applets). We simply draw the current frame onto the screen. Loading Images over the WebAs you experiment with this code youll discover that it sometimes jerks a bit. This happens when the image doesnt load fast enough to support the animation, particularly when someone is loading this applet over the Internet. A simple fix to this problem requires only six lines of code. You add an instance of the MediaTracker class to your applet. The MediaTracker knows which images are already loaded into memory and can prevent you from using an image that has not been fully loaded. A step-by-step procedure for adding a MediaTracker to any animation project follows:
|
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement. |