無論多複雜,遊戲本質只有三塊:
兩種驅動模式:
0. 初始化
1. 若結束條件 → 6
2. 搜集輸入
3. 運行邏輯
4. 更新並顯示下一幀
5. 跳回 1
6. 清理資源,退出
讓 Canvas 實作 Runnable,在 run() 中跑迴路:
public void run() {
boolean exit = false;
long frameStart, frameTime;
final int MIN_DELAY = 50; // 目標 20 FPS
gameInit(); // 0. 初始化
while (!exit) {
frameStart = System.currentTimeMillis();
acquireInput(); // 2. 輸入緩衝
gameLoop(); // 3. 邏輯更新
repaint(); // 4. 觸發渲染
serviceRepaints(); // 強制立即繪製 (MIDP 2.0)
frameTime = System.currentTimeMillis() - frameStart;
int sleep = MIN_DELAY - (int)frameTime;
if (sleep < 1) sleep = 1;
try { Thread.sleep(sleep); } catch (InterruptedException e) {}
}
endGame(); // 6. 收尾
}
gameInit():載入資源、建立物件、重置變數。acquireInput():將硬體事件轉為幀緩衝狀態 (見下)。gameLoop():核心邏輯 (AI、物理、碰撞、狀態機)。repaint() + serviceRepaints():雙重保證畫面更新。MIN_DELAY 設定單幀最小時間,快機睡眠、慢機全速跑,速度一致。1000 * 總幀數 / 總耗時 (平均值)。keyPressed/Released 由系統執行緒呼叫,與遊戲迴路非同步。// 三大狀態位圖
static int keyState = 0; // 當前按下狀態
static int pressedState = 0; // 本幀新按下
static int releasedState = 0; // 本幀釋放
// 邏輯鍵位元定義
final static int KEY_UP = 1 << 0;
final static int KEY_DOWN = 1 << 1;
final static int KEY_LEFT = 1 << 2;
final static int KEY_RIGHT = 1 << 3;
final static int KEY_FIRE = 1 << 4;
// ...
public void keyPressed(int keyCode) {
int bit = getKeyBit(keyCode); // 硬體碼 → 邏輯位
keyState |= bit;
pressedState |= bit; // 記錄本幀有按下
}
public void keyReleased(int keyCode) {
int bit = getKeyBit(keyCode);
keyState ^= bit; // 異或清除對應位
releasedState |= bit; // 記錄本幀有釋放
}
static int frameKey, framePressed, frameReleased;
private static void acquireInput() {
frameKey = keyState;
framePressed = pressedState;
frameReleased = releasedState;
pressedState = 0; // 清空,供下一幀收集
releasedState = 0;
}
在 while 迴路最開頭呼叫 acquireInput(),之後邏輯只讀取快照變數,保證同一幀判斷一致。
// 是否長按 (含上一幀就按住)
static boolean keyHeld(int key) { return (frameKey & key) != 0; }
// 是否本幀剛按下
static boolean keyDown(int key) { return (framePressed & key) != 0; }
// 是否本幀剛釋放
static boolean keyUp(int key) { return (frameReleased & key) != 0; }
private static int getKeyBit(int keyCode) {
switch (keyCode) {
case -1: case 50: return KEY_UP; // 不同機型實測值
case -2: case 51: return KEY_DOWN;
case -3: case 52: return KEY_LEFT;
case -4: case 53: return KEY_RIGHT;
case -5: case 10: return KEY_FIRE;
default: return 0;
}
}
支援多機型鍵碼,可擴展為啟動時自動偵測或玩家自定義。
下一章將深入:狀態機架構、場景管理、資源載入與釋放策略。