2014-11-08 41 views
1

我嘗試編寫自己的遊戲循環。但CPU使用率太高。這大概是25%。 我的問題可能是沒有Thread.sleep。但我不想用它,因爲它應該不是很準確。另外計算下一幀可能需要10毫秒。Java:遊戲循環 - CPU使用率過高

我的代碼是這樣做的:
1:重新繪製窗口(「芬斯特」是在德國窗口)
2:讀出毫秒
3:設置下一幀
我想有50 fps的。所以程序每幀需要等待1000/50 = 20毫秒。
4:計算的時間和設置下一幀

 // GameSchleife 
     while (true) { 

      // First repaint 
      fenster.repaint(); 

      // Before calculating the next frame, capture the time 
      long a = System.currentTimeMillis(); 
      long b = a; 

      // Calculate the next frame 
      fenster.Update(); 

      // Wait for 20 ms (50 frames in a second) 
      for (int time = 0; time < 20;) { 

       // Wait for at least 1 ms 
       while (a == b) { 
        a = System.currentTimeMillis(); 
       } 

       // Difference from a and b 
       time = time + ((int) (a - b)); 

       // 
       a = System.currentTimeMillis(); 
       b = a; 

      } 
     } 
+0

那麼,什麼是你的題? – 2014-11-08 16:48:27

回答

4

後的差額爲什麼了Thread.Sleep比你的代碼不準確的?你有沒有測試過它,發現它不準確? 如果你不想睡20ms,將睡眠分成幾部分,調整最後的睡眠時間,使總時間爲20ms。

事情是這樣的:(我是C#開發,所以你可能需要調整代碼中使用一點)

while (true) 
{ 
    long startTime = System.currentTimeMillis(); 

    fenster.repaint(); 

    long remaining= 20 - (System.currentTimeMillis() - startTime); 
    Thread.sleep(remaining - 2); // adds up to 18 ms since start if repaint took 10ms 

    remaining= 20 - (System.currentTimeMillis() - startTime); 
    Thread.sleep(remaining); // should be 1-2ms 
} 

你現在會殺死在任何時間任何筆記本電腦電池的代碼,並可能給予你其他的加熱問題。

編輯: 添加fenster.repaint()。還修復了代碼,以便重繪+等待總計20ms。如果重繪時間超過18ms,此代碼將會中斷,因此請添加一些測試。

另一個編輯澄清: 您的框架需要10ms來繪製。要達到50 fps,每幀總共有20ms,即如果重新繪製了11ms,則在繪製下一幀之前,您必須睡眠9ms。

startTime先分配,然後重新繪製,取appx 10ms。 重新繪製後,我們再次檢查系統計時器,並減去開始時間以獲得流逝的時間。 然後我們從20中減去這個數字,得到毫秒數,直到下一次重繪。

然後我們進入睡眠狀態,但是在系統計時器不準確的情況下,減去2ms有一點餘量。我們再次重新計算剩餘時間(1-2ms)並進入另一個短暫的睡眠。

所有這些都會增加到20ms,並且您可以渲染下一幀。

+0

嗯...我不明白你的代碼?爲什麼不在開始時打(20)? 我沒有測試過它。 – LittleSatan 2014-11-08 16:59:25

+0

剛剛添加了一些額外的代碼,它有幫助嗎? – EventHorizon 2014-11-08 17:00:17

+0

哦是的,它的工作原理:3,但我增加了一個 如果(剩餘> = 2)Thread.sleep(剩餘 - 2); }所以它不會崩潰。 – LittleSatan 2014-11-08 18:08:12

0

這麼多的嵌套循環影響性能

while (true) { 
... 

// Wait for 20 ms (50 frames in a second) 
for (int time = 0; time < 20;) { 

// Wait for at least 1 ms 
while (a == b) { 

... 

你必須檢查每個差異20ms的,並試圖糾正錯誤每一秒左右......這樣的:

while (true) { 
    if (((int) System.currentTimeMillis() % 20) == 0) { 
     fenster.repaint(); 
     // Calculate the next frame 
     fenster.Update(); 
    } 
}