将Bitmask应用于BufferedImage

时间:2014-06-24 19:14:47

标签: java performance opengl bufferedimage bitmask

我正在用Java开发类似蠕虫的游戏(具有可破坏的地形和所有东西)。

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

让我详细解释一下这个过程:

  1. 每当发生抛射物碰撞时,我都会画一个黑色圆圈 地形蒙版(黑色表示透明,白色表示不透明像素)。

    public void drawExplosion(Vector2 position,BufferedImage explosionImage){
        Graphics2D gMask = (Graphics2D) terrainMask.getGraphics();
        gMask.drawImage(explosionImage,(int) position.x, (int) position.y, null);
        gMask.dispose();
    }
    
  2. 将黑色圆圈绘制到我的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);
       }
      }
     }
    }
    
  3. 在这些步骤之后,地形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的恒定游戏速度,最后一个)。

1 个答案:

答案 0 :(得分:1)

你能用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高级主题教程中的Compositing Graphics

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