Graphics2D性能问题

时间:2014-05-22 15:57:01

标签: java performance graphics2d

我是Java图形库的新手,我仍然在掌握它的局限性。下面我有一个Grid类的绘图函数,它绘制一个2D数组的tile作为填充矩形。

不是它与问题相关,而是缩放和偏移参数用于调整Grid的tile和tileSize变量,使得它在正确的位置和缩放上绘制屏幕。

我的问题是,当tile变量相当大时,这是否正常?我通常在屏幕上没有任何网格时获得大约500 fps,并且使用网格[10] [10]到[50] [50]没有明显的减少。但是在tile [1000] [1000]或者总绘制的1,000,000个矩形中,fps会下降到7。

我知道一百万是很多,但毕竟它们只是矩形,我的电脑可以在完全设置下像天际一样玩游戏没问题。我想象天际有超过一百万个多边形,它们带有各种高质量的纹理和光线,所以,为什么一百万个灰色正方形会出现这样的问题呢? Java的图形库真的很差吗?我期待太多了吗?或者,正如我怀疑的那样,是否有更好的方式来绘制这样的东西?

我可以提供主要类的paintComponent,如果这很重要,但它只是对_Grid.draw()的调用,所以我不会想到问题'那里..

public Graphics draw(Graphics g, double scale, Point offset) {

    Graphics2D g2 = (Graphics2D) g;

    for(int i = 0; i != this.tiles.length; i++) {
        for(int j = 0; j != this.tiles[0].length; j++) {

            boolean draw = true;

            if(this.tiles[i][j].type.equals("EMPTY")) {
                draw = false;
            } else if(this.tiles[i][j].type.equals("PATH")) {
                g2.setColor(Color.LIGHT_GRAY);
            } else if(this.tiles[i][j].type.equals("WALL")) {
                g2.setColor(Color.DARK_GRAY);
            }

            if(draw) {
                g2.fillRect((int)((this.xPos+i*this.tileSize)*scale + offset.x), 
                            (int)((this.yPos+j*this.tileSize)*scale + offset.y), 
                            (int)(this.tileSize*scale), 
                            (int)(this.tileSize*scale));
            }
        }
    }

    return g2;

}

2 个答案:

答案 0 :(得分:2)

Java的BufferedImage类很慢。这是一个众所周知的事实。如果你想进行快速图像处理,那么使用它是错误的工具。

此外像Skyrim这样的游戏正在使用显卡来完成大部分工作,使用Java Image这些东西都是在CPU中完成的。

你应该真正考虑使用游戏框架 - 有2个像Slick2d和3d像jMonkeyEngine3。

答案 1 :(得分:2)

您可能会考虑尝试的一些事项:

  1. 如果Graphics创建了原始BufferedImage对象,请考虑使用VolatileImage。正如其他人所说,这种绘制方法中的所有内容都是通过Swing Event Dispatch Thread在CPU上进行的,所以你只能使用一个CPU进行绘图(除非你在某处产生更多的Thread)。 VolatileImage,当用于双缓冲时,利用图形硬件,对于这种事情可以更快。

  2. 你正在进行TON的字符串比较,这可能非常慢。我会考虑将您的type字段重构为自定义enum,然后让enum定义自己的draw方法,该方法需要Graphics个对象,吸取自己。这样,你可以调用this.tyles[i][j].type.draw(g2)并依靠后期绑定来绘制正确的彩色矩形,从而消除String比较。

  3. 确保您只绘制屏幕上显示的内容。我对你的tiles数组一无所知,但是如果它比实际渲染到屏幕的数量大得多,那么你可能会浪费很多CPU周期。

  4. 这可能听起来很愚蠢,但实际上您实际需要的内存访问次数是其两倍。我假设您在源代码中的某处定义了Tile[][] tiles ...。在外部循环中,首先通过编写类似Tile[] row = tiles[i];的内容来获取行,然后在内部循环中,通过调用row[j].type来获取类型。这将在迭代tile数组时将内存访问次数减半。