[英]Java 2D Game slowing down without apparent reason
我用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毫秒,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
}
}
}
}
将每个对象与其他每个对象进行检查的“钝”方法如下所示:
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:
通过更改关卡的绘制方法,我终于能够摆脱速度下降的问题。 现在,我不再遍历每个斑点并绘制相应的图像,而是先遍历不同的图像,然后遍历斑点(针对每个图像),然后绘制它们是否属于该斑点。
因此,总的来说,我的循环是numberOfImages更长的时间,但是速度消失了。 原因似乎是我现在绘制每个图像的次数与需要绘制的一样,然后继续下一个图像。 但是,即使绘制所需的时间没有改变,我也不知道这对我的整体帧率有多大影响?
根据drawImage的规范: https ://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html#drawImage(java.awt.Image,%20java.awt.geom.AffineTransform , %20java.awt.image.ImageObserver)
绘制可以异步完成,这意味着函数返回时不会渲染图像。 通过使用Thread.sleep阻塞线程,可能会减慢渲染速度。 您可以通过检查返回值进行快速测试,以检查图像是否完全渲染。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.