1

几天以来,我一直在使用 slick for java,但遇到了一个严重的问题。如果我使用 800x600 的解决方案运行一个完全空的应用程序(它只显示 fps),我会得到 700 到 800 之间的 fps 计数。如果我现在将一个包含 13300 个条目的数组绘制为绿色和白色矩形网格,则 fps 下降到70左右。

随着数组中的条目越来越多,它变得非常慢。例如,在 1024x768 的解决方案和具有 21760 个条目的数组中,fps 下降到 40。

我如何绘制一个条目:

public void draw(Graphics graphics){
    graphics.setColor(new Color(getColor().getRed(), getColor().getGreen(), getColor().getBlue(), getColor().getAlpha()));

    graphics.fillRect(getPosition().x, getPosition().y, getSize().x, getSize().y);

    Color_ARGB white = new Color_ARGB(Color_ARGB.ColorNames.WHITE);
    graphics.setColor(new Color(white.getRed(), white.getGreen(), white.getBlue(), white.getAlpha()));
}

这就是我绘制完整数组的方式:

public void draw(Graphics graphics) {
    for (int ix = 0; ix < getWidth(); ix++) {
        for (int iy = 0; iy < getHeight(); iy++) {
            getGameGridAt(ix, iy).draw(graphics);
        }
    }
}

在我看来,21760 并没有那么多。我的代码有什么问题吗,或者是因为太慢而无法绘制这么多矩形?

4

5 回答 5

1

您只想绘制屏幕上的矩形。如果您的屏幕边界在 x 方向上从 0 到 1024,在 y 方向上从 0 到 768,那么您只想遍历这些边界内的矩形,然后只绘制这些矩形。我无法想象您正在尝试在这些边界内绘制 21760 个矩形。

如果是,那么尝试创建一个静态矩形,然后尝试在您需要绘制它的所有不同位置绘制该 ONE,而不是每次都创建一个新矩形。例如,在我正在制作的游戏中,我可能有 1000 个“草”图块,但所有 1000 个图块共享相同的静态纹理。所以我只需要引用一个图像,而不是每个图块都创建自己的图块。

每个矩形仍然可以具有唯一的状态。只需创建自己的矩形类并拥有一个包含 5*5 图像的静态最终图像。每个矩形在需要绘制时都会使用该图像。您仍然可以为每个矩形拥有独特的属性。例如,私有 Vector2f 位置、私有布尔 isAlive 等

于 2012-09-17T22:17:00.763 回答
0

您可能无法比这更快地绘制单个矩形。

每秒渲染数百万个多边形的游戏使用顶点缓冲区对象 (VBO)。为此,您可能需要针对 OpenGL API (LWJGL) 本身而不是包装器进行编码。

于 2012-09-17T22:13:47.807 回答
0

由于您只重复使用几种颜色,因此为每一种颜色创建一个新的 Color 对象肯定会很慢......对于使用的每种不同颜色只使用一次 new 并将可重复使用的颜色存储在您班级的某处,而不是用那些调用函数,不断分配和释放内存非常慢。

虽然这可能不如不使用 new 每次都有好处,但是您是否考虑过缓存所有这些函数调用的结果并将代码重写为

public void draw(Graphics graphics) {
    int ixmax = getWidth();
    int iymax = getHeight();
    for (int ix = 0; ix < ixmax; ix++) {
        for (int iy = 0; iy < iymax; iy++) {
            getGameGridAt(ix, iy).draw(graphics);
        }
    }
}

或者,如果您不想声明新变量

public void draw(Graphics graphics) {
    for (int ix = getWidth() - 1; ix >= 0; ix--) {
        for (int iy = getHeight() - 1; iy >= 0; iy--) {
            getGameGridAt(ix, iy).draw(graphics);
        }
    }
}
于 2012-09-17T22:16:25.257 回答
0

不确定 Slick 是否允许,但如果这个东西看起来像棋盘格……你可以只画 4 个矩形,抓住它们并将生成的图像用作整个图像的纹理。我什至不是 Java 程序员,只是想提出一个解决方案。

于 2012-09-17T22:28:24.307 回答
0

刚刚在另一个答案中注意到你有一个整体大小的网格(5x5)......在这种情况下,最快的方法似乎是将每个项目绘制一个像素(你可以直接在内存中使用 2-维数组)并将其缩放到 500% 或将其用作纹理并用它绘制一个矩形,并使用它达到您想要的最终大小......应该非常快。很抱歉之前的答案造成的所有混乱,你应该从一开始就更清楚地说明你在做什么。如果缩放和纹理不可用,您仍然可以使用类似这样的东西在内存中绘制(用 c++ 编写,请自行翻译成 java)

for( int x = 0; x < grid.width(); x++ ) {
   for( int y = 0; y < grid.height(); y++ ) {
      image[x*5][y*5] = grid.color[x][y];
      image[x*5][y*5 + 1] = grid.color[x][y];
      image[x*5][y*5 + 2] = grid.color[x][y];
      image[x*5][y*5 + 3] = grid.color[x][y];
      image[x*5][y*5 + 4] = grid.color[x][y];
   }
   memcpy(image[x*5+1], image[x*5], grid.height() * sizeof(image[0][0]) );
   memcpy(image[x*5+2], image[x*5], grid.height() * sizeof(image[0][0]) );
   memcpy(image[x*5+3], image[x*5], grid.height() * sizeof(image[0][0]) );
   memcpy(image[x*5+4], image[x*5], grid.height() * sizeof(image[0][0]) );
}

我不确定,但也许对于图形,x 和 y 的表示顺序可能与此处使用的顺序相反,因此如果是这种情况,请相应地更改代码(只要运行几次迭代,您就会明白这一点) ,您的数据的结构也可能有所不同,但我认为这个想法应该很清楚。

于 2012-09-18T09:34:00.630 回答