我在java中创建了一个2D平台游戏风格的游戏,其中一些部分由我自己编程的物理引擎模拟。问题是游戏在某些点上从预期的60 fps减慢到大约30 fps。游戏循环看起来像这样:
@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();
}
}
我正在测量使用updateTime更新游戏逻辑所需的时间以及使用drawTime和drawscreenTime绘制所需的时间。在任何时候(在减速期间!),updateTime为0 ms,drawTime + drawscreenTime大约为10 ms,低于16 ms的最大值(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
}
}
}
}
&#34;直言不讳&#34;用每个其他对象来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的速度上下跳跃。
如果有人可以帮助我,我真的很感激。 如果你需要更多代码,我可以发布更多,但由于游戏代码已经相当大,我认为最好从小做起,而不是更多地淹没我的问题。
修改
似乎绘制游戏级别也会对减速产生影响。但是,当有更多图像要绘制时,它不会减慢速度,而是在图像较少时减慢速度。但同样重要的是:即使减速正在减少,当有更多东西需要绘制时,drawTime也会增加。绘制关卡的代码如下所示:
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);
}
}
}
数组中的图像是通过构造函数中的BufferedImage.getSubImage()生成的。
编辑2:
我终于能够通过改变我关卡的绘图方法来摆脱减速。我现在不是遍历每个点并绘制相应的图像,而是首先迭代不同的图像然后(对于每个图像)遍历斑点并绘制它们(如果它们属于斑点)。
总的来说,我的循环次数是数字时间更长,但减速消失了。原因似乎是我现在正在绘制每个图像,因为它需要绘制,然后继续下一个图像。但我不明白这对我的整体帧率有多大影响,即使绘制所需的时间不是更改?
答案 0 :(得分:0)
绘图可以异步完成,这意味着函数返回时不会渲染图像。通过使用Thread.sleep阻塞线程,可能会减慢渲染速度。您可以通过检查返回值来快速测试以检查图像是否完全呈现。