我是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;
}
答案 0 :(得分:2)
Java的BufferedImage
类很慢。这是一个众所周知的事实。如果你想进行快速图像处理,那么使用它是错误的工具。
此外像Skyrim这样的游戏正在使用显卡来完成大部分工作,使用Java Image这些东西都是在CPU中完成的。
你应该真正考虑使用游戏框架 - 有2个像Slick2d和3d像jMonkeyEngine3。
答案 1 :(得分:2)
您可能会考虑尝试的一些事项:
如果Graphics
创建了原始BufferedImage
对象,请考虑使用VolatileImage
。正如其他人所说,这种绘制方法中的所有内容都是通过Swing Event Dispatch Thread在CPU上进行的,所以你只能使用一个CPU进行绘图(除非你在某处产生更多的Thread)。 VolatileImage
,当用于双缓冲时,利用图形硬件,对于这种事情可以更快。
你正在进行TON的字符串比较,这可能非常慢。我会考虑将您的type
字段重构为自定义enum
,然后让enum
定义自己的draw
方法,该方法需要Graphics
个对象,吸取自己。这样,你可以调用this.tyles[i][j].type.draw(g2)
并依靠后期绑定来绘制正确的彩色矩形,从而消除String
比较。
确保您只绘制屏幕上显示的内容。我对你的tiles
数组一无所知,但是如果它比实际渲染到屏幕的数量大得多,那么你可能会浪费很多CPU周期。
这可能听起来很愚蠢,但实际上您实际需要的内存访问次数是其两倍。我假设您在源代码中的某处定义了Tile[][] tiles ...
。在外部循环中,首先通过编写类似Tile[] row = tiles[i];
的内容来获取行,然后在内部循环中,通过调用row[j].type
来获取类型。这将在迭代tile数组时将内存访问次数减半。