2014-06-24 50 views
1

我正在Java中開發類似蠕蟲的遊戲(具有可破壞的地形和所有內容)。將位掩碼應用於BufferedImage

一切都沒有好,直到我試圖更新地形圖像使用位掩碼。

讓我詳細解釋這個過程:

  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後,我通過設置 每個像素爲0更新我的可見地形BufferedImage如果terrainMask的像素是黑色的在同一位置。

    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()滯後不會發生。所以我的問題是如何更有效地將位掩碼應用到 a BufferedImage

重要提示:使用 GraphicsConfiguration.createCompatibleImage()方法將所有BufferedImages轉換爲兼容的。

當我在BufferedImage上調用getData()來獲得像素陣列時,fps下降到 〜23 fps,使得遊戲無法播放,所以這不是一個選項。

我還設置System.setProperty("sun.java2d.opengl","True");

爲啓用OpenGL的管道。另一個奇怪的事情是,每當我不設置openGL屬性時,我的遊戲速度超過700 fps(OpenGL啓用140 - 250 fps),我的筆記本電腦完全凍結。我的遊戲循環與此處所述的相同:http://www.koonsolo.com/news/dewitters-gameloop/(恆定遊戲速度獨立於變量FPS,最後一個)。

+0

討厭這麼說,但你做錯了。如果你想在OpenGL中有效地做到這一點,你應該使用着色器和緩衝區對象,而不是使用CPU讀取數據並向GL發送新數據。 –

+0

感謝您的答覆!你有使用着色器和緩衝區對象的有用教程嗎?雖然我設置了opengl屬性,但我不明白它的作用,以及如何有效地使用它,除了使圖像兼容。如果你在談論JOGL:不幸的是,我不允許使用第三方庫。 – flilip

+0

那我就不擔心了。學習如何使用GLSL需要付出很大的努力。如果您試圖滿足某些禁止使用第三方庫的截止日期/軟件要求,那麼爲了提高性能,您應該堅持使用原始非易失性存儲器, GL代碼路徑。如果您錯誤地使用了GL,GL實際上會傷害您的表現,這就是其中一個例子。 –

回答

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()覆蓋的矩形)。沒有必要更新你不知道的像素......

+0

令人驚歎!但是,是否有另一個規則來擦除源圖像的黑色部分(1bpp Bitmap B/W)而不是透明的部分?用你的方法,我將不得不製作一個版本來繪製我的terrainMask(黑色=刪除空間,alpha =無)和一個版本(黑色=無,alpha =刪除空間)以繪製到我的地形。對不起我的英語,我來自德國..給我最好的:) – flilip

+1

我跟着你的鏈接合成圖形,找到合適的人。它是'DstOut' :)非常感謝你!這幫了我很多! :) – flilip

+0

酷! :-)我在優化技巧中修正了一個錯字,並在那裏使用了錯誤的變量。但看起來你現在正走在正確的軌道上! :-) – haraldK