我正在用Java开发类似蠕虫的游戏(具有可破坏的地形和所有东西)。
一切都很好,直到我尝试使用位掩码更新地形图像。
让我详细解释一下这个过程:
每当发生抛射物碰撞时,我都会画一个黑色圆圈 地形蒙版(黑色表示透明,白色表示不透明像素)。
public void drawExplosion(Vector2 position,BufferedImage explosionImage){
Graphics2D gMask = (Graphics2D) terrainMask.getGraphics();
gMask.drawImage(explosionImage,(int) position.x, (int) position.y, null);
gMask.dispose();
}
将黑色圆圈绘制到我的terrainMask BufferedImage
后,其类型为
BufferedImage.TYPE_BYTE_INDEXED
,我通过设置更新我的可见地形BufferedImage
如果terrainMask的像素在同一位置是黑色,则每个像素为0。
public void mapUpdate(){
for(int x = 0 ; x < terrainMask.getWidth(); x++){
for(int y = 0 ; y < terrainMask.getHeight(); y++){
if(terrainMask.getRGB(x, y) == -16777216){
terrain.setRGB(x, y, 0);
}
}
}
}
在这些步骤之后,地形BufferedImage
会更新,并且每个看起来都很好,显示了
地形上的爆炸孔。
我的问题出现了:
每当我拨打mapUpdate()
时,游戏会停止300-500毫秒,检查2400 * 600像素并在检查结果为真时在地形中设置透明像素。
如果没有setRGB()
,则不会出现延迟。所以我的问题是如何应用位掩码
更有效率BufferedImage
。
重要提示:所有BufferedImages
都会转换为兼容的
GraphicsConfiguration.createCompatibleImage()
方法。
当我在getData()
上调用BufferedImage
来获取像素数组时,fps将降至
〜23 fps使游戏无法播放,所以这不是一个选择。
我还设置了System.setProperty("sun.java2d.opengl","True");
启用OpenGL Pipeline。另一个奇怪的事情是,每当我没有设置openGL属性时,我的游戏达到700 fps以上(openGL启用140 - 250 fps),我的笔记本电脑完全冻结。我的游戏循环与此处描述的相同:http://www.koonsolo.com/news/dewitters-gameloop/(独立于可变FPS的恒定游戏速度,最后一个)。
答案 0 :(得分:1)
你能用Java(即没有OpenGL)做到这一点的最快方法是:
a)将遮罩(terrainMask
)图像的颜色更改为白色和透明(而不是白色和黑色)。我想,只需更改颜色表(IndexColorModel
)即可。
b)使用正确的alpha复合规则替换双getRGB/setRGB
循环,在地形上绘制遮罩。由于查找,颜色转换和可能的数据类型转换(均取决于您的图像),setRGB
和getRGB
都可能是慢速操作,因此通常应避免在性能关键代码中使用它们。更新的代码可能如下所示:
public void mapUpdate() {
Graphics2D g = terrain.createGraphics();
try {
g.setComposite(AlphaComposite.DstIn); // Porter-Duff "destination-in" rule
g.drawImage(terrainMask); // Clear out transparent parts from terrainMask
}
finally {
g.dispose();
}
}
这样做也应该保持你的图像管理(即没有fps掉落)。
有关AlphaComposite
的更多信息,请参阅Java2D高级主题教程中的Compositing Graphics。
PS:你可以做的另一个优化,就是只更新爆炸覆盖的terrain
部分(即position.x, position.y, explosionImage.getWidth(), explosionImage.getHeight()
覆盖的矩形)。无需更新您不知道的像素......