/*
* Copyright (c) 2000-2001 Sun Microsystems, Inc. All Rights Reserved.
*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
/**
* A MIDlet that displays the Doggy animation.
*
* @author Mark A. Patel - Motorola, Inc.
* @author Roger Riggs - Sun Microsystems, Inc.
**/
public class DoggyMIDlet extends MIDlet implements CommandListener {
Command cmdExit;
/**
* Constructs a new DoggyMIDlet
**/
public DoggyMIDlet() {
cmdExit = new Command("Exit", Command.EXIT, 1);
}
/**
* Starts the app by creating a new Doggy instance and displaying it
**/
protected void startApp() throws MIDletStateChangeException {
Doggy d;
d = new Doggy();
d.addCommand(cmdExit);
d.setCommandListener(this);
Display.getDisplay(this).setCurrent(d);
}
protected void pauseApp() {
}
protected void destroyApp(boolean unconditional)
throws MIDletStateChangeException {
}
public void commandAction(Command c, Displayable d) {
if (c == cmdExit) {
try {
destroyApp(false);
} catch (Exception e) {}
notifyDestroyed();
}
}
}
class Doggy extends Canvas implements Runnable {
/**
* Number of frames in the animation
**/
static final int FRAME_COUNT = 17;
/**
* Normal frame delay (milliseconds)
**/
static final int FRAME_DELAY = 180;
/**
* Frame delay for the last frame where the dog is sleeping
**/
static final int LAST_FRAME_DELAY = 3000;
/**
* Relative horizontal position where each of the frames
* should be rendered. 0 represents the left edge of the screen
* and 1024 represents the right edge of the run distance
* (1024 is used so that scaling can be performed using
* simple bit shifts instead of division operations).
**/
static final int[] framePositions = {
0, 50, 186, 372, 558, 744, 930, 1024, 1024,
834, 651, 465, 279, 93, 0, 0, 0
};
/**
* An Image containing the 17 frames of the dog running,
* stacked vertically.
* Using a single image is much more efficient than using several
* images with each containing a single frame.
* Each frame can be rendered seperately by setting the clip
* region to the size of a single frame and then
* rendering the image at the correct position so that the desired
* frame isaligned with the clip region.
**/
Image doggyImages = null;
/**
* Width of a single animation frame
**/
int frameWidth = 0;
/**
* Height of a single animation frame
**/
int frameHeight = 0;
/**
* Index of the current frame
**/
int frameIndex = 0;
/**
* The distance, in pixels, that the dog can run (screen width less
* the width of a single frame)
**/
int runLength = 0;
/**
* Indicates if the animation is currently running
**/
boolean running = false;
/**
* Called when this Canvas is shown. This method starts the timer
* that runs the animation sequence.
**/
protected void showNotify() {
if (doggyImages == null) {
try {
doggyImages =
Image.createImage("/examples/animation/Doggy.png");
frameWidth = doggyImages.getWidth();
frameHeight = doggyImages.getHeight() / FRAME_COUNT;
} catch (Exception ioe) {
return; // no image to animate
}
}
runLength = getWidth() - frameWidth;
running = true;
frameIndex = 0;
new Thread(this).start();
}
/**
* Called when this Canvas is hidden. This method stops the
* animation timer to free up processing
* power while this Canvas is not showing.
**/
protected void hideNotify() {
running = false;
}
public void run() {
// Need to catch InterruptedExceptions and bail if one occurs
try {
while (running) {
Thread.sleep((frameIndex == FRAME_COUNT - 1) ?
LAST_FRAME_DELAY : FRAME_DELAY);
// Remember the last frame index so we can compute
// the repaint region
int lastFrameIndex = frameIndex;
// Update the frame index
frameIndex = (frameIndex + 1) % FRAME_COUNT;
// Determine the left edge of the repaint region
int repaintLeft = framePositions[lastFrameIndex];
int repaintRight = framePositions[frameIndex];
if (framePositions[lastFrameIndex] > framePositions[frameIndex]) {
repaintLeft = framePositions[frameIndex];
repaintRight = framePositions[lastFrameIndex];
}
// Scale the repaint coordinates to the width of the screen
repaintLeft = (repaintLeft * runLength) >> 10;
repaintRight = (repaintRight * runLength) >> 10;
// Trigger a repaint of the affected portion of the screen
// Repaint the region where the last frame was rendered
// (ensures that it is cleared)
repaint(repaintLeft, 0,
frameWidth + repaintRight - repaintLeft, frameHeight);
}
} catch (InterruptedException e) {}
}
public void paint(Graphics g) {
// Clear the background (fill with white)
// The clip region will limit the area that
// actually gets cleared to save time
g.setColor(0xFFFFFF);
g.fillRect(0, 0, getWidth(), getHeight());
// Translate the graphics to the appropriate
// position for the current frame
g.translate((framePositions[frameIndex] * runLength) >> 10, 0);
// Constrain the clip region to the size of a single frame
g.clipRect(0, 0, frameWidth, frameHeight);
// Draw the current frame by drawing the entire image with
// the appropriate vertical offset so that the desired frame
// lines up with the clip region.
g.drawImage(doggyImages, 0, -(frameIndex * frameHeight),
Graphics.LEFT + Graphics.TOP);
}
}
|