How do you double buffer in java for a game?

Ryley Matos picture Ryley Matos · May 9, 2012 · Viewed 33.2k times · Source

So in the game I'm working on, I have a marble follow the mouse, but when it does this the screen flickers.

The background includes two jpegs and 9 rectangles. How would I go about double buffering this? Here is the code for the main window.

/**
 * 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)
    {

    }
}

Answer

dfb picture dfb · May 9, 2012

Double buffering is conceptually pretty simple, instead of drawing your objects one by one, you draw them on an image and then tell the renderer to draw that entire image. This eliminates the flickering.

Here's an example of how you might do this (source)

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);
    }
}

Nowdays, you don't have to implement this yourself, you can use the BufferStrategy and releated classes. See lakam99's answer for an example of that .