遊戲 ≠ 事件驅動 GUI。專業遊戲採用**時間驅動主迴路**,每幀固定順序:
幀即某時刻畫面,遊戲 = 幀序列 + 玩家交互干預。
public void run() {
exitMidlet = false;
long startTime, timeCount;
gameInit();
int curKey = 0;
while (!exitMidlet) {
startTime = System.currentTimeMillis();
acquireKey(); // 輸入快照
gameLoop(); // 邏輯+渲染準備
repaint(); // 觸發 paint
serviceRepaints(); // 立即刷新
frameCount++;
// FPS 鎖定:MIN_DELAY=50 → 最高 20fps
timeCount = MIN_DELAY - (System.currentTimeMillis() - startTime);
timeCount = (timeCount < 1) ? 1 : timeCount;
try { Thread.sleep(timeCount); } catch (InterruptedException e) {}
}
endMidlet();
}
平均 FPS 計算:frames * 1000 / totalTime。
static int key, pressedKey, releasedKey; // 當前態/按下態/釋放態
final static int GKEY_0 = 1<<0, GKEY_1 = 1<<1, ...; // 虛擬鍵常量
public void keyPressed(int keyCode) {
int v = getKeyValue(keyCode); // 物理碼→虛擬碼
key |= v; // 當前按下
pressedKey |= v; // 本幀新按下
}
public void keyReleased(int keyCode) {
int v = getKeyValue(keyCode);
key ^= v; // 異或清除當前態
releasedKey |= v; // 本幀釋放
}
private static void acquireKey() {
frameKey = key;
framePressedKey = pressedKey;
frameReleasedKey = releasedKey;
pressedKey = releasedKey = 0; // 清空瞬態
}
public static boolean keyHold(int k) { return (frameKey & k) != 0; } // 長按
public static boolean keyDown(int k) { return (framePressedKey & k) != 0; } // 本幀按下
public static boolean keyUp(int k) { return (frameReleasedKey & k) != 0; } // 本幀釋放
keyHold:上一幀已按下並持續(移動、連發)keyDown:僅本幀觸發(跳躍、開槍、選單確認)keyUp:釋放瞬間(蓄力結束、鬆開方向)此為最小可用集;商業級擴展:連發計數、組合鍵狀態機、按鍵隊列回放。