遊戲需三大模組:渲染、輸入輸出、邏輯。專業遊戲採時間驅動:無論有無輸入,主迴圈持續「檢查輸入→運算邏輯→渲染幀」。最簡結構:
0 初始化
1 判斷結束?是→6
2 搜集輸入
3 運算邏輯
4 更新並顯示下一幀
5 跳回1
6 清理結束
讓 Canvas 實作 Runnable,run() 中執行 while(!exitMidlet) 迴圈。關鍵點:
gameInit() 初始化變數、載入資源、建立全域物件。acquireKey() 鍵盤緩衝(詳後)。gameLoop() 核心邏輯與圖形處理。repaint() + serviceRepaints() 刷新螢幕。MIN_DELAY(如 50ms → 最高 20 FPS),若幀耗時不足則 Thread.sleep() 補足。平均 FPS = 累計幀數 * 1000 / 累計耗時。public void run() {
exitMidlet = false;
long startTime = 0, timeCount = 0;
gameInit();
int curKey = 0;
while (!exitMidlet) {
startTime = System.currentTimeMillis();
acquireKey();
gameLoop();
repaint();
serviceRepaints();
frameCount++;
timeCount = MIN_DELAY - (System.currentTimeMillis() - startTime);
timeCount = (timeCount < 1) ? 1 : timeCount;
try { Thread.sleep(timeCount); } catch (InterruptedException ex) {}
}
endMidlet();
}
直接在 keyPressed/Released 處理邏輯會分散代碼且無法處理無按鍵時的持續邏輯。專業做法:用三個 int 位圖記錄鍵盤狀態:
key:當前按下狀態(位為1表按下)。pressedKey:本幀新按下的鍵。releasedKey:本幀釋放的鍵。常量定義:GKEY_0 = 1<<0、GKEY_1 = 1<<1 … 利用位運算設定/清除位。
public void keyPressed(int keyCode) {
int value = getKeyValue(keyCode);
key |= value;
pressedKey |= value;
}
public void keyReleased(int keyCode) {
int value = getKeyValue(keyCode);
key ^= value; // 異或清除位
releasedKey |= value;
}
acquireKey() 在迴圈伊始拷貝三狀態至 frameKey、framePressedKey、frameReleasedKey,並清空 pressedKey/releasedKey 供下幀使用。提供三個查詢函式:
keyHold(gameKey):鍵是否持續按住(至少從上一幀開始)。keyDown(gameKey):本幀是否被按下。keyUp(gameKey):本幀是否被釋放。此為最簡單單次緩衝,連擊需更複雜機制。