3

I am currently using a JPanel to draw the elements from my game, however, there is occasional stuttering with the graphics, after some research I learnt about screen tearing and double buffering, which I believe is the solution to my problem, however, currently with my code I am finding it extremely difficult to implement without tearing out a lot of code.

I am wondering if anyone could possibly provide either a simpler way to fix my screen tearing on a small 2D tile based game, or how to do double buffering with my current code, thank you very much!

Frame.java

public class Frame extends JPanel implements KeyListener {

public static Game game;
public static boolean[] mouseDown = new boolean[4];
public static int width, height;
public static Font font = new Font("Arial", Font.BOLD, 16);
public static JFrame frame;
public Frame()
{
    setFocusable(true);
    requestFocus();
    setOpaque(true);
    addKeyListener((KeyListener) this);
    addMouseListener(new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {
        }
        @Override
        public void mouseReleased(MouseEvent e) {

        }
    });
    addMouseMotionListener(new MouseMotionListener() {
        @Override
        public void mouseMoved(MouseEvent e) {
        }
        @Override
        public void mouseDragged(MouseEvent e) {
        }
    });
}

@Override
public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    g2d.setBackground(Color.BLACK);
    g2d.setFont(font);
    super.setBackground(Color.BLACK);
    super.paintComponent(g2d);
    //This is where I use g2d to draw onto the JPanel
}

public static void main(String[] args) {
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            frame = new JFrame("Game");
            frame.add(new Frame());
            frame.setSize(1000, 750);
            frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }});
}

Game.java

    public void gameStart() { 

    Thread gameThread =  new Thread() {
        // Override run() to provide the running behavior of this thread.
        @Override
        public void run() {
            gameLoop();
        }
    };
    // Start the thread. start() calls run(), which in turn calls gameLoop().
    gameThread.start();
}

public void gameLoop() {
    while (!isGameFinished) {
        beginTime = System.nanoTime();
        gameUpdate();
        frame.repaint();
        // Delay timer to provide the necessary delay to meet the target rate
        timeTaken = System.nanoTime() - beginTime;
        timeLeft = (UPDATE_PERIOD_NSEC - timeTaken) / 1000000L;  // in milliseconds
        if (timeLeft < 10) timeLeft = 10;   // set a minimum
        try { // Provides the necessary delay and also yields control so that other thread can do work.
            Thread.sleep(timeLeft);
        } catch (InterruptedException ex) { }
    }
}

public void gameStart() { 

    Thread gameThread =  new Thread() {
        // Override run() to provide the running behavior of this thread.
        @Override
        public void run() {
            gameLoop();
        }
    };
    // Start the thread. start() calls run(), which in turn calls gameLoop().
    gameThread.start();
}

public void gameLoop() {
    while (!isGameFinished) {
        beginTime = System.nanoTime();
        gameUpdate();
        frame.repaint();
        timeTaken = System.nanoTime() - beginTime;
        timeLeft = (UPDATE_PERIOD_NSEC - timeTaken) / 1000000L;
        if (timeLeft < 10) timeLeft = 10;   // set a minimum
        try { 
            Thread.sleep(timeLeft);
        } catch (InterruptedException ex) { }
    }
}

As shown in the code, the Game class contains the Game loop, which will constantly repaint the Frame class. How can I tweak this code to allow for double buffering to remove screen tearing? Thanks!

  • Don't modify the sate of the panel from within the paint method, this will setup additional paint cycles – MadProgrammer Aug 17 '14 at 11:21
  • Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This will result in less confusion and better responses – MadProgrammer Aug 17 '14 at 11:22
  • A complete example is examined [here](http://stackoverflow.com/a/3256941/230513). – trashgod Aug 17 '14 at 13:05

1 Answers1

0

Double buffering is the best way to fix it. Try calling Toolkit#sync (Toolkit.getDefaultToolkit().sync()) , which sometimes removes the issue. You won't be tearing down much code if you switch to double buffering, just move the code in paint to a separate method.

DaedalusUsedPerl
  • 772
  • 5
  • 9
  • 25