如何在Java中实现游戏的双缓冲?

9
在我正在开发的游戏中,我让一个弹球跟随鼠标移动,但是这样做会导致屏幕闪烁。
背景包括两个JPEG图像和9个矩形。我该如何实现双缓冲?以下是主窗口的代码。
/**
 * Write a description of class Window here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Window extends JApplet implements MouseMotionListener
{
    private BufferedImage image; 
    private BufferedImage side;
    private int mouseX;
    private int mouseY;

    public Window(){
        try {
            image = ImageIO.read(new File("Backgrounds/violet.jpg"));
            side = ImageIO.read(new File("Backgrounds/side margin.jpg"));
        } catch (IOException ex) { }    
    }   

    private void delay(int delay)
    {
        try {
            Thread.sleep(delay);
        } catch (InterruptedException e) {}
    }

    public void init()
    {
        this.addMouseMotionListener(this);
    }

    public void paint (Graphics page)
    {
        page.drawImage(image, 0, 0, null);
        page.setColor(Color.blue);
        page.fillRect(0, 0, 160, 160);
        page.setColor(Color.black);
        page.fillRect(15, 15, 130, 130);
        page.setColor(Color.green);
        page.fillRect(340, 0, 160, 160);
        page.setColor(Color.black);
        page.fillRect(355, 15, 130, 130);
        page.setColor(Color.yellow);
        page.fillRect(0, 340, 160, 160);
        page.setColor(Color.black);
        page.fillRect(15, 355, 130, 130);
        page.setColor(Color.red);
        page.fillRect(340, 340, 160, 160);
        page.setColor(Color.black);
        page.fillRect(355, 355, 130, 130);
        page.drawImage(side, 500, 0, null);
        page.drawString(Score.getScore(), 560, 110);
        //conveyors
        page.setColor(Color.gray);
        page.fillRect(235, 0, 30, 160);

        //marble
        delay(100);

        page.fillOval(mouseX, mouseY , 40, 40);          
    }

    public void mouseMoved(MouseEvent e)
    {
        mouseX = e.getX();
        mouseY = e.getY();
        repaint();
    }

    public void mouseDragged(MouseEvent e)
    {

    }
}
4个回答

21

双缓冲的概念相当简单,不是逐个绘制你的对象,而是将它们绘制在一张图像上,然后告诉渲染器绘制整个图像。这可以消除闪烁。

这里有一个如何实现双缓冲的例子(来源)

class DoubleBufferedCanvas extends Canvas {

    public void update(Graphics g) {
    Graphics offgc;
    Image offscreen = null;
    Dimension d = size();

    // create the offscreen buffer and associated Graphics
    offscreen = createImage(d.width, d.height);
    offgc = offscreen.getGraphics();
    // clear the exposed area
    offgc.setColor(getBackground());
    offgc.fillRect(0, 0, d.width, d.height);
    offgc.setColor(getForeground());
    // do normal redraw
    paint(offgc);
    // transfer offscreen to window
    g.drawImage(offscreen, 0, 0, this);
    }
}

现在,你不必自己实现它,你可以使用BufferStrategy和相关类。请参考lakam99的答案,其中有一个例子。


回答不错,但你不需要这样做,因为Swing已经提供了双缓冲。请参阅我的答案以获取详细信息... - mikera
@dfb 在你执行 'paint(offgc);' 后,离屏图像是如何更新的?我没有看到 offscreen 变量在任何地方被改变。 - DollarAkshay
看到这一行 offgc = offscreen.getGraphics(); - dfb

4
Swing自动支持双缓冲,因此您不需要编写任何代码。只需在顶级组件(通常是JPanel)上调用setDoubleBuffered(true),就可以使其正常工作。请参见:setDoubleBuffered

2

我认为你的问题不是双缓冲。你必须在绘制方法的第一行添加super.paint(page);


2
另一个解决方案是使用一个为您提供双缓冲的库。由于您正在使用Java2D,我假设您想保持一切相当轻量级和低级别。我认为Slick2D在提供简单的2D绘图和输入功能方面做得非常好,而且不会妨碍您。它感觉就像是Java2D的更优雅版本,但是是基于OpenGL编写的。一旦您用纯Java制作了几个应用程序,我认为转向Slick2D是一个很好的主意。这不是您问题的直接解决方案,但由于已经有人解决了这个问题,所以我想提供一些建议,使您的Java游戏开发生活更加轻松。如果有机会,请查看http://slick.cokeandcode.com/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接