響應 J2MEdev 站長號召,分享 2D 手機遊戲開發經驗。採用 MIDP 2.0 + Game API,開發工具 JBuilder。完整原始碼將於系列結束後提供下載。
MIDP 2.0 手機價格已下探至 1700 元左右(如 OT735i),主流機種(西門子 CX65、SE、Nokia 系列)皆支援。隨著硬體成本降低,未來 1500 元級 MIDP 2.0 手機將普及。
採用單例模式管理 GameCanvas,避免重複建立佔用寶貴記憶體。框架包含:
run()),固定 50ms 幀率(約 20 FPS)。gameInput()),支援長按與單擊邏輯分離。commandAction()):Start、Restart、Exit。start()、stop()、cleanJob() 釋放單例。public class MyGameCanvas extends GameCanvas implements Runnable, CommandListener {
private static MyGameCanvas instance;
private Graphics g;
private boolean running;
private Thread t;
// 按鍵狀態變數...
private boolean allowInput;
public int screenWidth, screenHeight;
private boolean gameOver;
protected MyGameCanvas() {
super(true); // 關閉系統按鍵繪製
g = getGraphics();
running = false;
// 命令初始化...
screenWidth = getWidth();
screenHeight = getHeight();
}
public static synchronized MyGameCanvas getInstance() {
if (instance == null) instance = new MyGameCanvas();
return instance;
}
public void run() {
long frameTime = 50; // ms
while (running) {
long st = System.currentTimeMillis();
gameInput();
gameMain();
long diff = System.currentTimeMillis() - st;
if (diff < frameTime) {
try { Thread.sleep(frameTime - diff); } catch (InterruptedException ignored) {}
}
}
}
private void gameMain() {
g.setColor(0,0,0);
g.fillRect(0,0,getWidth(),getHeight());
// background.paint(g);
flushGraphics();
}
private void gameInput() {
if (!allowInput) return;
int state = getKeyStates();
// UP, DOWN, LEFT, RIGHT, FIRE 狀態偵測邏輯...
}
public void commandAction(Command c, Displayable d) {
String cmd = c.getLabel();
if ("start".equals(cmd)) { gameInit(); start(); /* 切換命令 */ }
else if ("restart".equals(cmd)) { stop(); while(t.isAlive()); gameInit(); start(); }
else if ("exit".equals(cmd)) { stop(); Navigate.midlet.destroyApp(false); Navigate.midlet.notifyDestroyed(); }
}
}
GameCanvas 實例。Thread.sleep() 控制迴圈速度,避免佔滿 CPU。gameInput() 將鍵盤狀態轉為布林旗標,供遊戲邏輯使用。gameOver、allowInput 等旗標控制流程,為後續擴展奠基。下一篇將完善周邊工具類(圖片載入、GameObject、字體繪製)。