繁体   English   中英

Java 2D游戏无明显原因减速

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM