【问题标题】:triple buffer heavy flickering三重缓冲严重闪烁
【发布时间】:2013-07-20 22:46:25
【问题描述】:

三重缓冲和 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();

}

}

【问题讨论】:

  • 我会小心混合重量和重量轻的组件

标签: java swing awt buffer bufferstrategy


【解决方案1】:

我突然想到了两件事。

  1. 您的“循环”正在运行,没有任何延迟。这意味着屏幕将尽可能多地更新,这对于硬件来说可能跟不上。一般来说,您希望以 25fps 左右为目标,这有助于提供流畅运动的错觉
  2. 您没有准备Graphics 进行绘画。每次您从BufferStrategy 获得Graphics 上下文时,您实际上都获得了最后一次使用的上下文。这意味着,被绘制的一切都是静止的。在那里你需要清理它。闪烁(可能)来自以下事实: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();
        }
    }
}

【讨论】:

    【解决方案2】:

    试试这个:

    在您的 myPanel 类中创建一个 BufferedImage,如下所示:

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

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

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

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

    【讨论】:

    • 完美答案。谢谢。
    猜你喜欢
    • 2014-08-13
    • 2019-04-02
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    • 1970-01-01
    相关资源
    最近更新 更多