站内搜索: 请输入搜索关键词
当前页面: 图书首页 > Wireless Java Developing with J2ME, Second Edition

Driving Animation with GameCanvas - Wireless Java Developing with J2ME, Second Edition

Previous Section Next Section

Driving Animation with GameCanvas

GameCanvas extends javax.microedition.lcdui.Canvas with methods for animation and key state polling. GameCanvas is used differently than Canvas:

  • To use Canvas, you subclass it and define the paint() method. Inside paint(), you use a Graphics to render graphics on the screen. When you change something and want to update the screen, you call repaint() and the system calls paint() again for you.

  • To use GameCanvas, you subclass it. To draw on the screen, you use the Graphics returned from getGraphics(). When you want updates to appear on the screen, call flushGraphics(), which does not return until the screen is updated. For more specific updates, use the method flushGraphics(int x, int y, int width, int height), which only updates a region of the screen.

    public void flushGraphics(int x, int y, int width, int height)
    

GameCanvas's model of use makes it easy to use it inside a game loop like this:

Graphics g = getGraphics();
while(true) {
  // Check for user input.
  // Update game state.
  // Draw stuff using g.
  flushGraphics();
}

To subclass GameCanvas, you need to call its protected constructor from your subclass's constructor. This constructor accepts a single boolean argument, which indicates whether the normal key event mechanism should be suppressed for the GameCanvas instance. The normal key event mechanism refers to the callback mechanism of keyPressed(), keyReleased(), and keyRepeated(). Suppressing the normal mechanism may result in better performance. GameCanvas provides an alternate method for responding to key events, which is detailed in the next section.

To show how GameCanvas works for drawing, I'll rewrite the SweepCanvas example from Chapter 10 using GameCanvas. Note that the subclass no longer overrides paint(). All the action happens in run(), which is executed in a separate thread that drives the animation. The run() method calls render(), which does the actual drawing (and is identical to the old paint()).

Listing 11-1: Using GameCanvas for Animation
Start example
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

public class SweepGameCanvas
    extends GameCanvas
    implements Runnable {
private boolean mTrucking;
private int mTheta;
private int mBorder;
private int mDelay;
  public SweepGameCanvas() {
    super(true);
    mTheta = 0;
    mBorder = 10;
    mDelay = 50;
  }

  public void start() {
    mTrucking = true;
    Thread t = new Thread(this);
    t.start();
  }

  public void stop() {
    mTrucking = false;
  }

  public void render(Graphics g) {
    int width = getWidth();
    int height = getHeight();

    // Clear the Canvas.
    g.setGrayScale(255);
    g.fillRect(0, 0, width - 1, height - 1);

    int x = mBorder;
    int y = mBorder;
    int w = width - mBorder * 2;
    int h = height - mBorder * 2;
    for (int i = 0; i < 8; i++) {
      g.setGrayScale((8 - i) * 32 - 16);
      g.fillArc(x, y, w, h, mTheta + i * 10, 10);
      g.fillArc(x, y, w, h, (mTheta + 180) % 360 + i * 10, 10);
    }
  }

  public void run() {
    Graphics g = getGraphics();
    while (mTrucking) {
      mTheta = (mTheta + 1) % 360;
      render(g);
      flushGraphics();
      try { Thread.sleep(mDelay); }
      catch (InterruptedException ie) {}
    }
  }
}

End example

I'll assume you can write your own MIDlet to display SweepGameCanvas. If you've downloaded the online examples, SweepGame is a MIDlet that displays SweepGameCanvas.


Previous Section Next Section