三重缓冲区重闪烁

时间:2013-07-22 09:03:26

标签: java swing awt buffer bufferstrategy

不应该将三重缓冲和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();
 }

这是我放置Canvas

的JFrame类
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();

}

}

2 个答案:

答案 0 :(得分:2)

有两件事情发生在我身上。

  1. 您“循环”正在运行,没有任何延迟。这意味着屏幕将尽可能多次更新,这可能会让硬件跟上时间。一般来说,你想瞄准大约25fps,这有助于提供平稳运动的幻觉
  2. 你没有为绘画准备Graphics。每次从Graphics获得BufferStrategy上下文时,您实际上都会获得最后使用的内容。这意味着,绘制的所有内容仍然是。在那里你需要清理它。闪烁(可能)来自这样一个事实:Graphics个上下文中的一个已经填充了颜色,而其他情况则没有。
  3. 以下是一个非常基本的例子,包括一些动画

    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();
            }
        }
    }
    

答案 1 :(得分:1)

试试这个:

BufferedImage课程中设置myPanel,如下所示:

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

现在将此图像绘制在绘图方法中的其他所有内容上,如下所示:

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();
}

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(); }

这将在屏幕上绘制黑色背景,使其不再闪烁。现在,您可以在该图像上绘制任何内容。