原文見:http://today.java.net/pub/a/today/2005/07/07/j2me3.html?page=2
構(gòu)建一個J2ME游戲:從GameCanvas類開始
GameCanvas類繼承自Canvas,提供了一個屏幕后端的緩沖區(qū),所有的繪制操作都先在這個緩沖區(qū)里進行。當所有繪制操作完成后,我們調(diào)用flushGraphics()方法將緩沖區(qū)內(nèi)容輸出到屏幕。這種雙緩沖機制可以使圖像的移動更加平滑,避免圖像的閃爍。緩沖區(qū)大小等于屏幕的大小,而且每一個GameCanvas實例有且僅有一個緩沖區(qū)。
GameCanvas類提供一種存儲按鍵狀態(tài)的機制,我們可以通過它方便的了解用戶與游戲的交互。這種機制可以跟蹤用戶按特殊鍵的次數(shù),調(diào)用getKeyStates()方法返回所有游戲鍵按鍵狀態(tài)的二進制表示,1代表上次調(diào)用方法后按過該鍵,0表示上次調(diào)用后還沒有按過該鍵。我們可以跟蹤的游戲狀態(tài)有(這里的鍵都是在Canvas類里定義的):DOWN_PRESSED, UP_PRESSED, RIGHT_PRESSED, LEFT_PRESSED, FIRE_PRESSED, GAME_A_PRESSED, GAME_B_PRESSED, GAME_C_PRESSED和GAME_D_PRESSED。
首先擴展GameCanvas類,定制一個游戲畫布,代碼見清單1。清單2是運行例子的MIDlet。
package com.j2me.part3;

import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;

import java.io.IOException;

public class MyGameCanvas
extends GameCanvas
implements Runnable


{
public MyGameCanvas()

{
super(true);
}
public void start()

{
try

{
//導入couple圖片,坐標定位在屏幕中央
coupleImg = Image.createImage("/couple.gif");
coupleX = CENTER_X;
coupleY = CENTER_Y;
}
catch(IOException ioex)

{
System.err.println(ioex);
}
Thread runner = new Thread(this);
runner.start();
}
public void run()

{
//獲取畫布的graphics對象
Graphics g = getGraphics();
while(true) //無窮循環(huán)

{
//基于上一個代碼清單列出的結(jié)構(gòu)
//首先檢查游戲狀態(tài)
verifyGameState();
//檢查用戶輸入
checkUserInput();
//更新屏幕
updateGameScreen(getGraphics());
//休息一下,控制刷新頻率
try

{
Thread.currentThread().sleep(30);
}
catch(Exception e)

{}
}
}
private void verifyGameState()

{
//現(xiàn)在先不做任何操作
}
private void checkUserInput()

{
//獲取按鍵信息
int keyState = getKeyStates();
//計算x軸位置
calculateCoupleX(keyState);
}
private void updateGameScreen(Graphics g)

{
//清空屏幕背景
g.setColor(0xffffff);
g.fillRect(0, 0, getWidth(), getHeight());
//將couple圖片繪制到當前坐標位置
g.drawImage(
coupleImg, coupleX, coupleY, Graphics.HCENTER |
Graphics.BOTTOM);
flushGraphics();
}
private void calculateCoupleX(int keyState)

{
//判斷移動方向
if((keyState & LEFT_PRESSED) != 0)

{
coupleX -= dx;
}
else if((keyState & RIGHT_PRESSED) != 0)

{
coupleX += dx;
}
}
private Image coupleImg;
private int coupleX;
private int coupleY;
private int dx = 1; //移動量
//屏幕中心
public final int CENTER_X = getWidth() / 2;
public final int CENTER_Y = getHeight() / 2;
}
清單 1. MyGameCanvas:游戲畫布的第一個版本
清單 2 是使用這個游戲畫布的MIDlet:
package com.j2me.part3;

import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;

public class GameMIDlet extends MIDlet


{
MyGameCanvas gCanvas;
public GameMIDlet()

{
gCanvas = new MyGameCanvas();
}
public void startApp()

{
Display d = Display.getDisplay(this);
gCanvas.start();
d.setCurrent(gCanvas);
}
public void pauseApp()

{}
public void destroyApp(boolean unconditional)

{}
}
清單 2. 運行游戲示例的MIDlet類
使用Wireless工具建立一個工程,導入這兩個類,然后生成并運行工程。確保你的工程目錄res中有這個圖片文件
,并保證名稱為couple.gif, 圖1是運行結(jié)果。

圖1. 構(gòu)建一個游戲:使用GameCanvas類
使用設備的方向鍵可以左右移動屏幕中的小圖像,這是通過從checkUserInput()里取得按鍵狀態(tài),然后調(diào)用calculateCoupleX(),通過將按鍵狀態(tài)與GameCanvas里預定義的按鍵值進行與操作(&),得到用戶當前按的鍵,然后將實例變量更新,最終反映到設備屏幕上。
圖像是在updateGameScreen()方法里被繪制到屏幕上的。這個方法使用傳入的Graphics對象進行繪制,每一個GameCanvas只有一個Graphics對象。方法首先擦除上次繪制的圖像,然后基于當前的coupleX值(還有一直不變的coupleY值)繪制couple.gif圖像,最后將緩沖區(qū)的數(shù)據(jù)輸出到屏幕。
run()方法里的循環(huán)體遵循我們剛開始提出的游戲結(jié)構(gòu)。循環(huán)每30毫秒檢查一次用戶輸入并刷新屏幕。你可以試著將這個值改變一下,這會改變刷新的頻率。
最后,注意MyGameCanvas的構(gòu)造器里調(diào)用了父類GameCanvas的構(gòu)造方法,傳入的參數(shù)為true,這表示從Canvas類繼承的按鍵事件機制被抑制了,因為我們的代碼不需要這些通知機制。我們的游戲狀態(tài)用GameCanvas里自帶的按鍵信息(由getKeyStates()方法取得)來處理已經(jīng)足夠了。通過抑制“keyPressed”、“keyReleased”和“keyRepeated”等通知機制,可以提高游戲的性能。
版權(quán)所有 羅明