2017-07-30 32 views
1

我在java中創建了一個2D平臺遊戲風格的遊戲,其中一些部分被我自己編程的物理引擎模擬。問題在於遊戲在某些點從預期的60 fps下降到30 fps左右。遊戲循環如下所示:Java 2D遊戲沒有明顯的原因放慢

@Override 
public void run() { 

    init(); 

    long startTime; 
    long elapsedTime; 
    long waitTime; 

    while(running) { 

     startTime = System.nanoTime(); 

     update(); 
     long updateTime = (System.nanoTime() - startTime)/1000000; 
     draw(); 
     long drawTime = (System.nanoTime() - startTime)/1000000; 
     drawToScreen(); 
     long drawscreenTime = (System.nanoTime() - startTime)/1000000; 

     elapsedTime = System.nanoTime() - startTime; 
     waitTime = targetTime - elapsedTime/1000000; 
     if(waitTime < 0) { 
      waitTime = 0; 
     } 

     try { 
      Thread.sleep(waitTime); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

我測量是需要的更新錄入,同時還需要有drawTime和drawscreenTime繪製時間的遊戲邏輯的時間。在任何時候(在減速過程中!),更新時間爲0毫秒,drawTime + drawscreenTime約爲10毫秒,低於最大值16毫秒(對於60 fps)。

到目前爲止,我發現改變我的物理對象的潛在碰撞的設置可以減緩放緩。起初我想按區域分隔對象,這樣程序就不需要檢查每個對象的每個對象。例如,而不是100x100 = 10000對象只有33x33 + 33x33 + 33x33 = 3267對象。

分隔條件的區域是這樣的:

private ArrayList<PhysicalObject> objects; 
private ArrayList<ArrayList<PhysicalObject>> zones; 

for(int i = 0; i < numberOfZones; i++) { 
     zones.get(i).clear(); 
    } 

    for(PhysicalObject object : objects) { 
     for(int zone : object.getSimulationZones()) { 
      zones.get(zone).add(object); 
     } 
    } 

    for(ArrayList<PhysicalObject> list : zones) { 

     for(PhysicalObject object1 : list) { 
      for(PhysicalObject object2 : list) { 

      collision stuff happens 

      } 
     } 
    } 
} 

chekcing每個對象與所有其他對象的「鈍」的做法是這樣的:

private ArrayList<PhysicalObject> objects; 

for(PhysicalObject object1 : objects) { 
    for(PhysicalObject object2 : objects) { 

     collision stuff happens 
    } 
} 

現在,正如你所預料的生硬做法查看updateTime時速度較慢,但​​是當我使用這種方法時,減速效果遠沒有那麼顯着。 我不知道這是怎麼發生的,因爲做一個遊戲循環所需的時間似乎與減速無關,但是當我更改在遊戲循環中運行的代碼時,減速是變化的。

起初我以爲Thread.sleep()可能有錯,因爲我聽說它有時不可靠,所以我嘗試使用Java.util.Timer。但是當我用16毫秒的延遲(對於60 fps)時,fps會以大約30 fps的速度上下跳動。

我真的很感激,如果有人能幫助我這個。 如果你需要更多的代碼,我可以發佈更多的代碼,但由於遊戲代碼已經很大,我認爲最好從小開始,而不是讓我的問題氾濫。

編輯:

似乎繪製遊戲級對放緩的影響力。但是當有更多的圖像繪製時,不要放慢速度,而是在圖像較少時減慢速度。但是,再次說明:儘管減速正在減少,但當需要繪製更多東西時,延伸時間正在增加。繪製電平的代碼看起來是這樣的:通過BufferedImage.getSubImage()在構造產生

public void draw(Graphics2D g2d) { 

    for(int row = drawStartRow; row < drawStartRow + rowsToDraw; row++) { 

     if(row >= numRows) { 
      break; 
     } 

     for(int col = drawStartCol; col < drawStartCol + colsToDraw; col++) 
{ 

      if(col >= numCols) { 
       break; 
      } 

      //0 stands for no tile to draw 
      if(map[row][col] == 0) { 
       continue; 
      } 

      int rc = map[row][col]; 
      int r = rc/numTilesAcross; 
      int c = rc % numTilesAcross; 

      g2d.drawImage(tiles[r][c].getImage(), (int)x + col * tileSize, (int)y + row * tileSize, null); 
     } 
    } 
} 

在數組中的圖像。

編輯2:

我終於能夠改變我的水平的繪製方法擺脫放緩的。我不是迭代每個點並繪製相應的圖像,而是先迭代不同的圖像,然後(對於每個圖像)遍歷這些點並繪製它們,如果它們屬於該點。

因此整體上我的循環是倍數numberOfImages更長,但減速消失。原因似乎是,我現在正在繪製每個圖像,因爲它需要繪製,然後繼續下一個圖像。但我不明白這是如何影響我的整體幀率這麼多,即使繪製所需的時間不是更改?

+1

變量太多。你甚至沒有提到你的PC如果不夠強大可能是原因。我會分析應用程序,看看它大部分時間花在哪裏。 – Warrior

+0

我的電腦運行在intel i5-4670K @ 3.40 Ghz並帶有16 Gb RAM。我認爲它應該能夠處理它。 – Aschas

+0

要真正檢查你是否有麻煩,請檢查每幀的時間,從開始到結束(意思是直到「Thread.sleep」之後),因爲睡眠並不保證它會爲其參數睡眠,而是* *至少爲**(當然,直到中斷)。如果你的JVM比較老舊和/或不是熱點,那麼'sleep'使用的增量可能仍然會以每片15-16毫秒的片段發生!附: 'java.util.Timer'在內部使用'Thread'及其方法。如果您懷疑某個元素,請不要使用第一個使用第一個元素的其他元素。 –

回答