тройной буфер сильное мерцание

Разве тройная буферизация и Canvas не должны быть оптимальным решением для пассивного рендеринга? Я только что написал этот код Java, который отображает круг. Если я оставлю bufferstrategy на 3, он так сильно мерцает. Если я уменьшу его до 2 или 1, все в порядке. Может я что-то не так делаю?

public void run(){

    while (running){   
        update();
        draw();
    }
 }


 public void update(){

 }


 public void draw(){
       BufferStrategy bs = getBufferStrategy();
       if (bs==null){
       createBufferStrategy(3);
       return;
       }

       Graphics g = bs.getDrawGraphics();
       g.setColor(Color.BLACK);
       g.fillOval(30, 30, 20, 20);
       g.dispose();
       bs.show();
 }

и это класс JFrame, в который я помещаю Canvas

public class Game {

public static void main (String [] args){

    Pan game = new Pan();
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(true);
    frame.add(game);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    game.start();

}

}

person Muteking    schedule 22.07.2013    source источник
comment
Я был бы осторожен при смешивании тяжелых и легких компонентов.   -  person MadProgrammer    schedule 22.07.2013


Ответы (2)


Две вещи бросаются мне в глаза.

  1. Ваш «цикл» работает без каких-либо задержек. Это означает, что экран будет обновляться столько раз, сколько возможно, это может быть слишком много для аппаратного обеспечения. Вообще говоря, вы хотите стремиться к 25 кадрам в секунду, это поможет создать иллюзию плавного движения.
  2. Вы не готовите Graphics к покраске. Каждый раз, когда вы получаете контекст Graphics из BufferStrategy, вы фактически получаете последний использованный контекст. Это означает, что все, что было нарисовано, неподвижно. Вот это надо почистить. Мерцание (возможно) происходит из-за того, что один из Graphics контекстов уже заполнен цветом, а другие нет.

Ниже приведен очень простой пример, включающий небольшую анимацию.

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;

public class DoubleBuffer {

    public static void main(String[] args) {

        Pan game = new Pan();
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(true);
        frame.add(game);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        game.start();

    }

    public static class Pan extends Canvas implements Runnable {

        private int xDelta = 2;
        private int x = 0;
        private int y = 20;

        public Pan() {
        }

        public void start() {
            new Thread(this).start();
        }

        public void run() {

            while (true) {
                update();
                try {
                    Thread.sleep(40);
                } catch (InterruptedException ex) {
                }
                draw();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        public void update() {
            x += xDelta;
            if (x + 20 > getWidth()) {
                x = getWidth() - 20;
                xDelta *= -1;
            } else if (x < 0) {
                x = 0;
                xDelta *= -1;
            }
        }

        public void draw() {
            BufferStrategy bs = getBufferStrategy();
            if (bs == null) {
                createBufferStrategy(3);
                return;
            }

            Graphics g = bs.getDrawGraphics();
            g.setColor(Color.RED);
            g.fillRect(0, 0, getWidth(), getHeight());
            g.setColor(Color.BLACK);
            g.fillOval(x, y, 20, 20);
            g.dispose();
            bs.show();
        }
    }
}
person MadProgrammer    schedule 22.07.2013

Попробуй это:

Создайте BufferedImage в своем классе myPanel следующим образом:

private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

Now draw that image ABOVE everything else in your draw method like this:

public void draw(){
   BufferStrategy bs = getBufferStrategy();
   if (bs== null){
       createBufferStrategy(3);
       return;
   }

   Graphics g = bs.getDrawGraphics();
   g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
   // Draw your other stuff after this...
   g.fillOval(20, 20, 20, 20);
   g.dispose();
   bs.show();
}

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

person H3XXX    schedule 22.07.2013
comment
Идеальный ответ. Спасибо. - person Muteking; 22.07.2013