GameCanvas是Canvas的子類,因此他同樣持續了Canvas類的一些特征,比如showNotify()方法會在Canvas被顯示在屏幕的時候調用,而hideNotify()會在Canvas離開屏幕的時候被調用。我們可以把他們當作*********來應用,用於初始化和燒毀資源。比如
// When the canvas is shown, start a thread to
// run the game loop.
protected void showNotify()
{
random = new Random();
thread = new Thread(this);
thread.start();
}
// When the game canvas is hidden, stop the thread.
protected void hideNotify()
{
thread = null;
}
在游戲開發中最重要的就是接收用戶觸發的事件然後重新繪制屏幕,通常我們應用getKeyStates()方法判定哪個鍵被按下了,然後繪制屏幕,調用flushGraphics()。在GameCanvas中,系統事實上已經為我們實現了雙緩沖技巧,因此每次我們繪制的時候就是在off- screen上繪制的。結束後通過flushGraphics把它復制到屏幕上往。下面是典范的接收事件、處理邏輯、繪制屏幕的代碼。
// Get the Graphics object for the off-screen buffer
Graphics g = getGraphics();
while (true) {
// Check user input and update positions if necessary
int keyState = getKeyStates();
if ((keyState & LEFT_PRESSED) != 0) {
sprite.move(-1, 0);
}
else if ((keyState & RIGHT_PRESSED) != 0) {
sprite.move(1, 0);
}
// Clear the background to white
g.setColor(0xFFFFFF);
g.fillRect(0,0,getWidth(), getHeight());
// Draw the Sprite
sprite.paint(g);
// Flush the off-screen buffer
flushGraphics();
}
下面開端實現我們轉動星空的後果,實在設計的思想非常簡略。我們啟動一個線程,應用copyArea()方法把屏幕的內容往下復制一個像素的間隔。然後繪畫第一個空缺的直線,隨機的在直線上繪畫點兒,這樣看起來就像星空一樣了。邏輯代碼如下:
// The game loop.
public void run()
{
int w = getWidth();
int h = getHeight() - 1;
while (thread == Thread.currentThread())
{
// Increment or decrement the scrolling interval
// based on key presses
int state = getKeyStates();
if ((state & DOWN_PRESSED) != 0)
{
sleepTime += SLEEP_INCREMENT;
if (sleepTime > SLEEP_MAX)
sleepTime = SLEEP_MAX;
} else if ((state & UP_PRESSED) != 0)
{
sleepTime -= SLEEP_INCREMENT;
if (sleepTime < 0)
sleepTime = 0;
}
// Repaint the screen by first scrolling the
// existing starfIEld down one and painting in
// new stars...
graphics.copyArea(0, 0, w, h, 0, 1, Graphics.TOP | Graphics.LEFT);
graphics.setColor(0, 0, 0);
graphics.drawLine(0, 0, w, 0);
graphics.setColor(255, 255, 255);
for (int i = 0; i < w; ++i)
{
int test = Math.abs(random.nextInt()) % 100;
if (test < 5)
{
graphics.drawLine(i, 0, i, 0);
}
}
flushGraphics();
// Now wait...
try
{
Thread.currentThread().sleep(sleepTime);
} catch (InterruptedException e)
{
}
}
}
下面給出源代碼
/*
* License
*
* Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
*
*/
import Javax.microedition.lcdui.*;
import Javax.microedition.lcdui.game.*;
import Javax.microedition.midlet.*;
public class GameCanvasTest extends MIDlet implements CommandListener
{
private Display display;
public static final Command exitCommand = new Command("Exit", Command.EXIT,
1);
public GameCanvasTest()
{
}
public void commandAction(Command c, Displayable d)
{
if (c == exitCommand)
{
exitMIDlet();
}
}
protected void destroyApp(boolean unconditional)
throws MIDletStateChangeException
{
exitMIDlet();
}
public void exitMIDlet()
{
notifyDestroyed();
}
public Display getDisplay()
{
return display;
}
protected void initMIDlet()
{
GameCanvas c = new StarFIEld();
c.addCommand(exitCommand);
c.setCommandListener(this);
getDisplay().setCurrent(c);
}
protected void pauseApp()
{
}
protected void startApp() throws MIDletStateChangeException
{
if (display == null)
{
display = Display.getDisplay(this);
initMIDlet();
}
}
}
/*
* License
*
* Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
*/
import Java.util.Random;
import Javax.microedition.lcdui.*;
import Javax.microedition.lcdui.game.GameCanvas;
// A *** example of a game canvas that displays
// a scrolling star fIEld. Use the UP and DOWN keys
// to speed up or slow down the rate of scrolling.
public class StarFIEld extends GameCanvas implements Runnable
{
private static final int SLEEP_INCREMENT = 10;
private static final int SLEEP_INITIAL = 150;
private static final int SLEEP_MAX = 300;
private Graphics graphics;
private Random random;
private int sleepTime = SLEEP_INITIAL;
private volatile Thread thread;
public StarFIEld()
{
super(true);
graphics = getGraphics();
graphics.setColor(0, 0, 0);
graphics.fillRect(0, 0, getWidth(), getHeight());
}
// The game loop.
public void run()
{
int w = getWidth();
int h = getHeight() - 1;
while (thread == Thread.currentThread())
{
// Increment or decrement the scrolling interval
// based on key presses
int state = getKeyStates();
if ((state & DOWN_PRESSED) != 0)
{
sleepTime += SLEEP_INCREMENT;
if (sleepTime > SLEEP_MAX)
sleepTime = SLEEP_MAX;
} else if ((state & UP_PRESSED) != 0)
{
sleepTime -= SLEEP_INCREMENT;
if (sleepTime < 0)
sleepTime = 0;
}
// Repaint the screen by first scrolling the
// existing starfIEld down one and painting in
// new stars...
graphics.copyArea(0, 0, w, h, 0, 1, Graphics.TOP | Graphics.LEFT);
graphics.setColor(0, 0, 0);
graphics.drawLine(0, 0, w, 0);
graphics.setColor(255, 255, 255);
for (int i = 0; i < w; ++i)
{
int test = Math.abs(random.nextInt()) % 100;
if (test < 5)
{
graphics.drawLine(i, 0, i, 0);
}
}
flushGraphics();
// Now wait...
try
{
Thread.sleep(sleepTime);
} catch (InterruptedException e)
{
}
}
}
// When the canvas is shown, start a thread to
// run the game loop.
protected void showNotify()
{
random = new Random();
thread = new Thread(this);
thread.start();
}
// When the game canvas is hidden, stop the thread.
protected void hideNotify()
{
thread = null;
}
}