遊戲核心是一個永不停止的迴路 (Game Loop)。在每一幀中,根據當前狀態 執行不同邏輯:
// 概念示意
int state = STATE_LOGO;
while (true) {
switch (state) {
case STATE_LOGO: drawLogo(); if (time>5s) state=STATE_MENU; break;
case STATE_MENU: drawMenu(); handleInput(); break;
case STATE_PLAY: updateGame(); drawGame(); break;
}
sleep(frameDelay); // 控制幀率
}
狀態機 = 無限迴路 + 狀態變數控制分支。整個遊戲、AI、選單皆可用此模式構建。
public class Game extends Canvas implements Runnable, CommandListener {
// ... 原有代碼
}
public void run() {
while (true) {
System.out.println("xx"); // 測試輸出
// 此處將放入:狀態判斷、邏輯更新、repaint()
}
}
// GameMidlet.startApp()
Display.getDisplay(this).setCurrent(gameCanvas);
new Thread(gameCanvas).start(); // 關鍵:啟動獨立執行緒跑 run()
為什麼要另開執行緒? 若直接在 startApp() 呼叫含 while(true) 的方法,系統主執行緒會卡死,無法處理鍵盤、來電、重繪等事件。獨立執行緒讓遊戲迴路與系統事件處理並行。
xx,代表執行緒正常運行,狀態機骨架搭建成功while 迴路執行一次 (邏輯更新 + 繪圖準備)1000 / SPF (毫秒制)final int TARGET_FPS = 20;
final int FRAME_DELAY = 1000 / TARGET_FPS; // 50ms
public void run() {
while (true) {
long start = System.currentTimeMillis();
// 1. 邏輯更新
// 2. repaint()
long elapsed = System.currentTimeMillis() - start;
int sleepTime = FRAME_DELAY - (int)elapsed;
if (sleepTime < 1) sleepTime = 1; // 至少睡 1ms 避免佔滿 CPU
try { Thread.sleep(sleepTime); } catch (InterruptedException e) {}
}
}
若單幀耗時超過 FRAME_DELAY,說明邏輯過重或手機太慢,需優化代碼或降低目標 FPS。
在 run() 中加入 FPS 計算並輸出到控制台:
long totalFrames = 0, totalTime = 0;
while (true) {
long start = System.currentTimeMillis();
// ... 遊戲邏輯 ...
totalFrames++;
totalTime += System.currentTimeMillis() - start;
if (totalFrames % 100 == 0) {
System.out.println("Avg FPS: " + (1000.0 * totalFrames / totalTime));
}
// ... sleep ...
}
繪圖系統流程:paint(Graphics g) 如何被呼叫、如何繪製圖形、查閱 API 文件技巧。