9

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

    }
}
Michael Yaworski
  • 13,410
  • 19
  • 69
  • 97
Ryley Matos
  • 137
  • 2
  • 2
  • 3

4 Answers4

21

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 .

dfb
  • 13,133
  • 2
  • 31
  • 52
  • good answer, but you don't need to do this as Swing already provides double buffering. See my answer for details.... – mikera May 09 '12 at 00:43
  • @dfb After you 'paint(offgc);' how does the Image offscreen get updated ? I don't see the variable offscreen getting changed anywhere. – DollarAkshay Jul 09 '14 at 23:26
  • See the line `offgc = offscreen.getGraphics();` – dfb Jul 09 '14 at 23:42
4

Swing supports double buffering automatically, so you don't need to code anything.

Just call setDoubleBuffered(true) on your top-level component (typically a JPanel) and it should all work.

See: setDoubleBuffered

mikera
  • 105,238
  • 25
  • 256
  • 415
2

I think your problem is not double buffering. You must add super.paint(page); at the first line of your paint method.

Taryn
  • 242,637
  • 56
  • 362
  • 405
ceklock
  • 6,143
  • 10
  • 56
  • 78
2

Another solution is to use a library that will double buffer for you. Since you are using Java2D I am assuming you want to keep everything pretty lightweight and lower level. I think Slick2D does a great job of providing simple, 2d drawing and input functions without getting in your way. It feels like a more elegant version of Java2D, but is written on OpenGL. Once you make a few applications with pure Java, I think moving to Slick2D is a GREAT idea. This is not a direct solution to your issue, but since it has already been solved I thought Id offer some advice that will make your Java game development life easier. Check it out if you get a chance http://slick.cokeandcode.com/

JParrilla
  • 213
  • 1
  • 2
  • 6