Как вы удваиваете буфер в java для игры?

Итак, в игре, над которой я работаю, шарик следует за мышью, но когда он это делает, экран мерцает.

Фон включает в себя два 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)
    {

    }
}

person Ryley Matos    schedule 08.05.2012    source источник


Ответы (4)


Двойная буферизация концептуально довольно проста: вместо того, чтобы рисовать объекты один за другим, вы рисуете их на изображении, а затем указываете рендереру нарисовать это изображение целиком. Это устраняет мерцание.

Вот пример того, как вы можете это сделать (источник)

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 для примера этого.

person dfb    schedule 08.05.2012
comment
хороший ответ, но вам не нужно этого делать, поскольку Swing уже обеспечивает двойную буферизацию. Подробности смотрите в моем ответе.... - person mikera; 09.05.2012
comment
@dfb После того, как вы «рисуете (offgc);» как обновляется изображение за кадром? Я не вижу, чтобы переменная за кадром где-либо менялась. - person DollarAkshay; 10.07.2014
comment
См. строку offgc = offscreen.getGraphics(); - person dfb; 10.07.2014

Swing автоматически поддерживает двойную буферизацию, поэтому вам не нужно ничего кодировать.

Просто вызовите setDoubleBuffered(true) в компоненте верхнего уровня (обычно это JPanel), и все должно работать.

См.: setDoubleBuffered

person mikera    schedule 09.05.2012

Другим решением является использование библиотеки, которая будет дублировать буфер для вас. Поскольку вы используете Java2D, я предполагаю, что вы хотите, чтобы все было довольно легковесным и низкоуровневым. Я думаю, что Slick2D отлично справляется с предоставлением простых функций 2D-рисования и ввода, не мешая вам. Похоже на более элегантную версию Java2D, но написана на OpenGL. После того, как вы сделаете несколько приложений на чистой Java, я думаю, что переход на Slick2D — это ОТЛИЧНАЯ идея. Это не прямое решение вашей проблемы, но, поскольку она уже решена, я подумал, что могу дать несколько советов, которые облегчат вашу жизнь при разработке игр на Java. Проверьте это, если у вас есть возможность http://slick.cokeandcode.com/

person JParrilla    schedule 09.05.2012

Я думаю, что ваша проблема не в двойной буферизации. Вы должны добавить super.paint(page); в первую строку вашего метода рисования.

person ceklock    schedule 09.05.2012