5

I'm working on a project and I've read up as much as I can on double buffering in java. What I want to do is add a component or panel or something to my JFrame that contains the double buffered surface to draw to. I want to use hardware acceleration if possible, otherwise use regular software renderer. My code looks like this so far:

  public class JFrameGame extends Game {

    protected final JFrame frame;
    protected final GamePanel panel;
    protected Graphics2D g2;

    public class GamePanel extends JPanel {

        public GamePanel() {
            super(true);
        }

        @Override
        public void paintComponent(Graphics g) {
            g2 = (Graphics2D)g;
            g2.clearRect(0, 0, getWidth(), getHeight());
        }
    }

    public JFrameGame() {
        super();
        gameLoop = new FixedGameLoop();

        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        panel = new GamePanel();
        panel.setIgnoreRepaint(true);
        frame.add(panel);

        panel.setVisible(true);
        frame.setVisible(true);
    }

    @Override
    protected void Draw() {
        panel.repaint(); // aquire the graphics - can I acquire the graphics another way?
        super.Draw(); // draw components

        // draw stuff here

        // is the buffer automatically swapped?
    }


    @Override
    public void run() {
        super.run();
    }
}

I created an abstract game class and a game loop that calls Update and Draw. Now, if you see my comments, that's my main area of concern. Is there a way to get the graphics once instead of going through repaint and paintComponent and then assigning a variable every redraw? Also, is this hardware accelerated by default? If not what should I do to make it hardware accelerated?

Boro
  • 7,913
  • 4
  • 43
  • 85
Caleb Jares
  • 6,163
  • 6
  • 56
  • 83
  • Related: http://stackoverflow.com/questions/2067255/bufferstrategy-vs-diy-double-buffering-in-jframe – finnw May 08 '11 at 00:12

2 Answers2

9

If you want more control over when the window is updated and to take advantage of hardware page flipping (if available), you can use the BufferStrategy class.

Your Draw method would then look something like this:

@Override
protected void Draw() {
    BufferStrategy bs = getBufferStrategy();
    Graphics g = bs.getDrawGraphics(); // acquire the graphics

    // draw stuff here

    bs.show(); // swap buffers
}

The downside is that this approach does not mix well with event-driven rendering. You generally have to choose one or the other. Also getBufferStrategy is implemented only in Canvas and Window making it incompatible with Swing components.

Tutorials can be found here, here and here.

finnw
  • 47,861
  • 24
  • 143
  • 221
2

Don't extend JPanel. Extend JComponent. It's virtually the same and has less interfering code. Also, you'd do the drawing code in paintComponent only. If you need to manually refresh the component, you'd use component.redraw().

Chris Dennett
  • 22,412
  • 8
  • 58
  • 84
  • 3
    Double buffering is enabled in Swing by default. See: http://java.sun.com/products/jfc/tsc/articles/painting/index.html#db – camickr May 08 '11 at 00:46
  • @camickr so you would suggest to use the default one even for a game? And, for example, use labels to paint images of objects you would normally render yourself. Thus instead of changing the location you paint your image you would change labels location? Do you have some article about this approach? – Boro May 08 '11 at 17:03
  • @Boro, I wasn't really recommending anything with my comment above. I was just pointing out that you don't need to explicitly turn on double buffering in Swing. I don't know whether it is better to use a JLabel or draw an Icon directly. Theoretically drawing the Icon directly should be more efficient because the JLabel painting code first has to check if there is text to paint and set the position of the Icon within the label etc. But is the real bottleneck the Graphics painting code or these few extra statements in the label painting code? – camickr May 08 '11 at 18:48
  • @Boro, changing the location is easier. Swing will determine what needs to be repainted (ie. you need to repaint the bacground of where the label was before painting where it now is). If you do your own painting you need to manage this yourself. If you game needs to repaint the entire screen anyway it probably isn't an issue. But if you are only moving a few icons here and there it may be easier to let Swing manage the repainting. I"ve never written a game to I don't have any real world experience. – camickr May 08 '11 at 18:53
  • @camickr thanks v. much for your answer. I have written few toy project games my self and I have been using both approaches. Generally it depends what is the game about. A simple button clicker would be great with labels especially that is handles mouse clicks etc. Where when I do some real time related I go for active rendering. But since you mentioned approach with labels on few posts now if I remember correctly I was wondering if you can offer some reading about this approach in context of game dev. Thanks again. – Boro May 08 '11 at 20:28