首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

J2ME 遊戲教學 (二):狀態機、遊戲迴路與 FPS 控制

     編輯:J2ME

什麼是狀態機?

遊戲核心是一個永不停止的迴路 (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、選單皆可用此模式構建。

在 JBuilder 專案中實作狀態機

1. 讓 Game 實作 Runnable

public class Game extends Canvas implements Runnable, CommandListener {
    // ... 原有代碼
}

2. 實作 run() 方法 — 遊戲主迴路

public void run() {
    while (true) {
        System.out.println("xx"); // 測試輸出
        // 此處將放入:狀態判斷、邏輯更新、repaint()
    }
}

3. 在 MIDlet 中啟動執行緒

// GameMidlet.startApp()
Display.getDisplay(this).setCurrent(gameCanvas);
new Thread(gameCanvas).start(); // 關鍵:啟動獨立執行緒跑 run()

為什麼要另開執行緒? 若直接在 startApp() 呼叫含 while(true) 的方法,系統主執行緒會卡死,無法處理鍵盤、來電、重繪等事件。獨立執行緒讓遊戲迴路與系統事件處理並行。

驗證狀態機運作

  1. 編譯執行專案
  2. 在模擬器按 Select 鍵 (通常對應 Fire/確定)
  3. 查看 JBuilder 控制台:若持續輸出 xx,代表執行緒正常運行,狀態機骨架搭建成功

幀與 FPS 核心概念

定義

  • 幀:while 迴路執行一次 (邏輯更新 + 繪圖準備)
  • SPF (Seconds Per Frame):單幀耗時
  • FPS (Frames Per Second):每秒幀數 = 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。

進階:動態幀率補償 (參考魔獸世界)

  • 網路延遲大 → 降低 FPS 維持同步
  • 網路恢復 → 提高 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 文件技巧。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved