2013-08-16 59 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); 

如果你真的想精确绘制的图像,没有缩放,并且侧面没有间隙,则禁用您的主窗口的大小调整并设置大小以匹配图像。