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

Thread.sleep(500) 真相:遊戲迴圈定時邏輯的正確寫法

     編輯:Java 相關知識

誤區:單純 sleep 導致幀率不穩

許多 J2ME 遊戲開發者在 Canvas 繼承類中實現 Runnable,使用如下迴圈:

public void run() {
    while (true) {
        gameLogic();
        repaint();
        Thread.sleep(500); // 以為固定 0.5 秒一幀
    }
}

問題: gameLogic() 與 paint() 執行耗時不固定(受 GC、邏輯複雜度影響),實際幀間隔 = 執行時間 + 500ms,導致畫面卡頓、速度忽快忽慢,破壞遊戲體驗。

正確做法:動態計算睡眠時間

目標:維持固定幀率(如 20 FPS → 50ms/幀)。每幀記錄開始時間,執行邏輯與繪圖後,計算耗時,剩餘時間才 sleep。

public void run() {
    final int RUN_RATE = 50; // 目標幀間隔 ms (20 FPS)
    long time0 = System.currentTimeMillis();

    while (true) {
        long time1 = System.currentTimeMillis();
        long elapsed = time1 - time0;
        time0 = time1;

        gameLogic();   // 遊戲邏輯
        repaint();     // 觸發 paint()

        time1 = System.currentTimeMillis();
        long logicPaintTime = time1 - time0; // 實際耗時
        long sleepTime = RUN_RATE - logicPaintTime;

        if (sleepTime > 0) {
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                // 處理中斷或忽略
            }
        }
        // 若 sleepTime <= 0 表示邏輯超時,立即進入下一幀(或記錄警告)
    }
}

關鍵點解析

  • 基準時間更新:time0 = time1 放在邏輯執行前,確保下一幀計算基準正確。
  • 睡眠時間保護:僅當 sleepTime > 0 才睡眠,避免負值導致異常或忙等待。
  • 精度考量:Thread.sleep 精度受 OS 排程影響(Windows ~10-15ms),高精度需求可考慮 System.nanoTime() + 忙等待混合策略。
  • J2ME 替代方案:Timer / TimerTask 或內部類實現定時器,語義更清晰,但同樣需處理執行超時情況。

進階:固定時間步長

物理模擬、網路同步常採用 固定時間步長:累積幀時間,以固定 dt 多次更新邏輯,渲染採用插值。此為專業遊戲引擎標準架構(參考 Gaffer on Games "Fix Your Timestep")。

總結

Thread.sleep(固定值) 是新手陷阱。專業遊戲迴圈必須 測量實際耗時、動態補償睡眠,才能保證幀率穩定、遊戲邏輯確定性。

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