简体   繁体   English

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

[英]Java 2D Game slowing down without apparent reason

i created a 2D platformer style game in java in which some parts are simualted by a physics-engine that i programmed myself as well. 我用Java创建了一个2D平台游戏风格的游戏,其中的某些部分也由我自己编程的物理引擎模拟。 The problem is that the game slows down to around 30 fps from the intended 60 fps at some points. 问题在于游戏在某些时候会从原先的60 fps减慢到30 fps。 The game loop looks like this: 游戏循环如下所示:

@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();
        }
    }

I am measuring the time that is needed to update the game logic with updateTime and the time that is needed to draw with drawTime and drawscreenTime. 我正在测量使用updateTime更新游戏逻辑所需的时间,以及使用drawTime和drawscreenTime进行绘制所需的时间。 At all times (during the slowdowns as well!) the updateTime is 0 ms and drawTime + drawscreenTime is around 10 ms, which is below the maximum of 16 ms (for 60 fps). 在任何时候(在减速过程中也是如此!),updateTime为0毫秒,drawTime + drawscreenTime约为10毫秒,低于最大16毫秒(对于60 fps)。

So far i have found out that changing the setup of potential collisions of my physical objects can reduce the slowdown. 到目前为止,我发现更改物理对象潜在碰撞的设置可以降低速度。 At first i wanted to seperate the objects by zones, so that the program doesnt need to check every object with every object. 起初,我想按区域分开对象,这样程序就不必检查每个对象的每个对象。 For example instead of 100x100 = 10000 objects only 33x33 + 33x33 + 33x33 = 3267 objects. 例如,不是100x100 = 10000个对象,而是仅33x33 + 33x33 + 33x33 = 3267个对象。

Seperating by zones looked like this: 按区域分隔看起来像这样:

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

            }
        }
    }
}

The "blunt" approach of chekcing every object with every other object looked like this: 将每个对象与其他每个对象进行检查的“钝”方法如下所示:

private ArrayList<PhysicalObject> objects;

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

        collision stuff happens
    }
}

Now as you might expect the blunt approach is slower when looking at updateTime, but when i use this approach the slowdowns are far less significant. 现在,正如您可能期望的那样,在查看updateTime时,钝化方法的速度较慢,但​​是当我使用此方法时,减慢的速度远没有那么明显。 I dont know how this is happening, since the time needed to do one game loop seems to be unrelated to the slowdowns, but when i change code that runs during the game loop, the slowdowns are varying. 我不知道这是怎么发生的,因为执行一个游戏循环所需的时间似乎与放慢速度无关,但是当我更改在游戏循环中运行的代码时,放慢速度是变化的。

At first i thought that Thread.sleep() might be at fault, since i heard that it is sometimes unreliable, so i tried using a Java.util.Timer. 起初我以为Thread.sleep()可能有问题,因为我听说它有时不可靠,所以我尝试使用Java.util.Timer。 But when i use that with a delay of 16 ms (for 60 fps) the fps are jumping up and down around 30 fps. 但是,当我以16毫秒(60 fps)的延迟使用它时,fps大约在30 fps上下跳跃。

I would really appreciate if someone could help me with this. 如果有人可以帮助我,我将非常感激。 If you need more Code, I can post more, but since the game-code is already pretty big I figured it would be best to start small and not flood my question even more. 如果您需要更多代码,我可以发布更多,但是由于游戏代码已经很大,我认为最好从小处开始,不要过多地提出我的问题。

EDIT: 编辑:

It seems that drawing the game-level has an influence on the slowdowns as well. 似乎绘制游戏级别也会影响减速。 But instead of slowing down when there are more images to draw, it slows down when there are less images. 但是,当绘制更多图像时,它不会减慢速度,而在绘制更少图像时,它会减慢速度。 But again: Even though the slowdowns are decreasing, the drawTime is increasing when there are more things to draw. 再说一遍:即使放慢速度在减小,但是当绘制更多内容时,drawTime也会增加。 The code for drawing the level looks like this: 绘制关卡的代码如下所示:

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);
        }
    }
}

The images in the array were generated via BufferedImage.getSubImage() in the constructor. 数组中的图像是通过构造函数中的BufferedImage.getSubImage()生成的。

EDIT 2: 编辑2:

I was finally able to get rid of the slowdowns by changing the drawing method of my level. 通过更改关卡的绘制方法,我终于能够摆脱速度下降的问题。 Instead of iterating over every spot and drawing the corresponding image, i am now iterating over the different images first and then (for every image) over the spots and drawing them if they belong to the spot. 现在,我不再遍历每个斑点并绘制相应的图像,而是先遍历不同的图像,然后遍历斑点(针对每个图像),然后绘制它们是否属于该斑点。

So overall my loop is times numberOfImages longer, but the slowdowns disappeared. 因此,总的来说,我的循环是numberOfImages更长的时间,但是速度消失了。 The reason seems to be that I am now drawing every image as often as it needs to be drawn and then going on to the next image. 原因似乎是我现在绘制每个图像的次数与需要绘制的一样,然后继续下一个图像。 But i dont understand how this is affecting my overall framerate so much, even though the time needed to draw is not changing? 但是,即使绘制所需的时间没有改变,我也不知道这对我的整体帧率有多大影响?

As per the specs of 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) 根据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)

The drawing may be done asynchronously, which means that the image is not rendered when the function returns. 绘制可以异步完成,这意味着函数返回时不会渲染图像。 By blocking the thread with Thread.sleep, you may be slowing the rendering. 通过使用Thread.sleep阻塞线程,可能会减慢渲染速度。 You can do a quick test to check if the image is fully rendered by checking the return value. 您可以通过检查返回值进行快速测试,以检查图像是否完全渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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