我在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更長,但減速消失。原因似乎是,我現在正在繪製每個圖像,因爲它需要繪製,然後繼續下一個圖像。但我不明白這是如何影響我的整體幀率這麼多,即使繪製所需的時間不是更改?
變量太多。你甚至沒有提到你的PC如果不夠強大可能是原因。我會分析應用程序,看看它大部分時間花在哪裏。 – Warrior
我的電腦運行在intel i5-4670K @ 3.40 Ghz並帶有16 Gb RAM。我認爲它應該能夠處理它。 – Aschas
要真正檢查你是否有麻煩,請檢查每幀的時間,從開始到結束(意思是直到「Thread.sleep」之後),因爲睡眠並不保證它會爲其參數睡眠,而是* *至少爲**(當然,直到中斷)。如果你的JVM比較老舊和/或不是熱點,那麼'sleep'使用的增量可能仍然會以每片15-16毫秒的片段發生!附: 'java.util.Timer'在內部使用'Thread'及其方法。如果您懷疑某個元素,請不要使用第一個使用第一個元素的其他元素。 –