我正在用Java开发类似于Worms的游戏(具有可破坏的地形和所有内容)。

一切都很好,直到我尝试使用位掩码更新地形图像。

让我详细解释该过程:


每当发生弹丸碰撞时,我都会在我的身上画一个黑圈
地形遮罩(黑色代表透明,白色代表不透明像素)。

public void drawExplosion(Vector2 position,BufferedImage explosionImage){
    Graphics2D gMask = (Graphics2D) terrainMask.getGraphics();
    gMask.drawImage(explosionImage,(int) position.x, (int) position.y, null);
    gMask.dispose();
}

将黑色圆圈绘制到我的地形中后,遮罩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像素,如果检查结果为true,则在地形中设置透明像素。

如果没有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/(恒定游戏速度独立于Variable FPS,最后一个)。

最佳答案

据我所知,在Java(即没有OpenGL)中执行此操作的最快方法是:

a)将蒙版(terrainMask)图像的颜色更改为白色和透明(而不是白色和黑色)。我猜只是更改颜色表(IndexColorModel)就可以。

b)使用正确的alpha合成规则,通过在地形上绘制蒙版来替换双getRGB/setRGB循环。由于查找,颜色转换和可能的数据类型转换(均取决于您的图像),setRGBgetRGB都可能是较慢的操作,因此在性能关键的代码中通常应避免使用它们。更新后的代码可能类似于以下内容:

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 Advanced Topics教程中的Compositing Graphics

PS:您可以做的另一种优化方法是仅更新爆炸所覆盖的terrain部分(即position.x, position.y, explosionImage.getWidth(), explosionImage.getHeight()覆盖的矩形)。无需更新您不知道的像素...

关于java - 将位掩码应用于BufferedImage,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24394515/

10-12 05:53