2013-08-16 65 views
3

我正在研究Java中的等距2D遊戲,並且我注意到屏幕上有一行網格,渲染似乎在水平和垂直方向重複一個像素。以下是截圖顯示了我的意思:Java 2D渲染紋波僞影

Screenshot

我進行循環在我的Render方法,比較每個像素的顏色值的數組中的前值,看看是否有兩個黑色像素的任何事件並且沒有發現這種情況。我對於可能造成這種影響的原因感到不知所措。我能做些什麼來解決這個問題?下面是相關的代碼:

遊戲類變量:

private BufferedImage m_imgImage = new BufferedImage(intCANVAS_WIDTH, intCANVAS_HEIGHT, BufferedImage.TYPE_INT_RGB); 
private int[ ] m_aintPixels = ((DataBufferInt) m_imgImage.getRaster().getDataBuffer()).getData(); 

Game類的Render方法:

// Object to organize data on the canvas 
BufferStrategy bfsBufferStrategy = getBufferStrategy(); 

if(bfsBufferStrategy == null) 
{ 
    createBufferStrategy(3); 
    return; 
} 

for(int intY = 0; intY < intCANVAS_HEIGHT; intY += 1) 
{ 
    for(int intX = 0; intX < intCANVAS_WIDTH; intX += 1) 
    { 
     m_aintPixels[ intX + (intY * intCANVAS_WIDTH) ] = m_Screen.m_aintPixels[ intX + (intY * m_Screen.m_intWidth) ]; 
    } 
} 

Graphics gfxGraphics = bfsBufferStrategy.getDrawGraphics(); 
gfxGraphics.drawImage(m_imgImage, 0, 0, getWidth(), getHeight(), null); 


gfxGraphics.dispose(); 
bfsBufferStrategy.show(); 

Screen類Render方法來填充像素陣列:

// Render a tile with the specified tile ID 
public void RenderTile(int intPositionX, int intPositionY, CSpriteSheet SpriteSheet, int intTileID) 
{ 

    int intPixelIndex = 0; 
    int intSheetX = 0; 
    int intSheetY = 0; 
    int intTileOffsetX = 0; 
    int intTileOffsetY = 0; 
    int intPixelColor = 0; 

    // Center the Tile 
    intPositionX -= m_intOffsetX; 
    intPositionY -= m_intOffsetY; 

    intSheetX = (intTileID % SpriteSheet.m_intTileColumns) * CTile.TILE_WIDTH; 
    intSheetY = (intTileID/SpriteSheet.m_intTileRows) * CTile.TILE_HEIGHT; 

    intPixelIndex = intPositionX + (intPositionY * m_intWidth); 

    // Rows 
    for(int intTileRow = intSheetY; intTileRow != (intSheetY + CTile.TILE_HEIGHT); intTileRow += 1) 
    { 
     // Columns 
     for(int intTileColumn = intSheetX; intTileColumn != (intSheetX + CTile.TILE_WIDTH); intTileColumn += 1) 
     { 
      intPixelColor = SpriteSheet.m_aintPixels[ intTileColumn + (intTileRow * m_SpriteSheet.m_intWidth) ]; 

      // Boundary checking 
      if(intPositionX + intTileOffsetX >= 0 && intPositionX + intTileOffsetX < m_intWidth && 
      intPositionY + intTileOffsetY >= 0 && intPositionY + intTileOffsetY < m_intHeight && 
      CColor.Transparent(intPixelColor) == false) 
      { 

       m_aintPixels[ intPixelIndex ] = SpriteSheet.m_aintPixels[ intTileColumn + (intTileRow * m_SpriteSheet.m_intWidth) ]; 
      } 

      // Increment 
      intTileOffsetX += 1; 
      intPixelIndex += 1; 
     } 

     // Increment 
     intTileOffsetY += 1; 
     intPixelIndex += m_intWidth - (CTile.TILE_WIDTH); 
     intTileOffsetX = 0; 
    } 
} 

回答

3

這是非插值縮放的經典人工產物。您有:

private BufferedImage m_imgImage = new BufferedImage(intCANVAS_WIDTH, intCANVAS_HEIGHT, BufferedImage.TYPE_INT_RGB); 
... 
gfxGraphics.drawImage(m_imgImage, 0, 0, getWidth(), getHeight(), null); 

你所看到的效果是因爲getWidth()getHeight()intCANVAS_WIDTHintCANVAS_HEIGHT稍大。繪製圖形時,它會將其縮放得更大。它沒有使用任何類型的縮放插值,只是從源選擇最近的像素;因此您會定期看到重複的行或列。

當您檢查源數據時,您看不到此數據,因爲它不在源數據中,它是數據呈現時輸出中引入的工件。

打印出圖像和麪板尺寸,你會看到一個區別。根據我看到的重複行的數量(我看到10個橫向和10個縱向)來判斷,我想你會發現getWidth()比高度更高的是intCANVAS_WIDTH

您可以改爲將m_imgImage的尺寸傳遞給.drawImage()。這將擺脫神器,但會留下一個空白的右側和底部,因爲圖像比組件小。

如果您Graphics實際上是一個Graphics2D,可以設置KEY_INTERPOLATION呈現提示縮放時使用插值(也可能不服從該提示):

Graphics2D g = (Graphics2D)gfxGraphics; 
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 

如果你真的想精確繪製的圖像,沒有縮放,並且側面沒有間隙,則禁用您的主窗口的大小調整並設置大小以匹配圖像。