在画布上闪烁的白色

时间:2014-07-03 17:26:26

标签: java canvas flicker

我在发布后的几分钟内找到了解决方案,但由于声誉不佳,我无法删除帖子

为了好玩,我决定开始研究可能在某些时候变成游戏的东西。

我试图绘制一些圆圈并将它们移动到当前给定的方向。这会导致闪烁。我很可能会监督一些非常基本的东西,但我无法弄清楚它为什么不能顺利渲染。

我的董事会类看起来像(删除了我认为不必要的东西):

public class Board extends Canvas implements Runnable {

    public static void main(String[] args) {
        Board board = new Board();

        board.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));

        JFrame frame = new JFrame("Circles");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(board);
        frame.pack();

        frame.setVisible(true);

        board.start();
    }

    @Override
    public void run() {
        while (running) {
            process();
            repaint();

            try {
                Thread.sleep(15);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

绘画方法:

    public void paint(Graphics g1) {
        super.paint(g1);
        Graphics2D g = (Graphics2D) g1;
        for (Ball ball : Ball.BALLS) {
            g.drawOval((int) ball.getLocation().getX(), (int) ball.getLocation().getY(), ball.getRadius(),  ball.getRadius());
        }
    }

我的处理方法:

private void process() {
    if (utilities.randInt(1, 100) < 10 && Ball.getBallCount() < 40) {
        Ball.spawnNew(this);
    }
    for (Ball ball : Ball.BALLS) {
        ball.move(this);
    }
    Ball.BALLS.removeAll(Ball.TO_REMOVE);
    Ball.TO_REMOVE.clear();
}

每次调用时,移动方法基本上会将球的x值增加一个给定的值(向右移动)。

就像我说的那样,我不确定为什么它会闪烁,所以如果你有任何指示,请告诉我们。

谢谢!

2 个答案:

答案 0 :(得分:1)

这听起来像是需要执行双缓冲的情况,因此在更新另一个时,可以保留一个画布副本。

你在这里使用AWT,我不知道如何用AWT手动实现双缓冲。但是,如果你愿意在这里使用Swing,你可以利用自动双缓冲。请参阅有关How to make canvas with Swing?的问题以及Oracle技术网关于Painting in AWT and Swing的文章。

基本理念是:

  1. 扩展javax.swing.JPanel而不是Canvas(这意味着当你覆盖paint(Graphics)时,你现在从javax.swing.JComponent而不是java.awt.Component覆盖它)
  2. 使用super(true)创建一个构造函数以启用双缓冲。
  3. 修改:另外,as iccthedral points out,您最好覆盖paintComponent(Graphics),并包括对super.paintComponent(Graphics)的调用。请参阅Difference between paint, paintComponent and paintComponents in Swing

答案 1 :(得分:1)

你需要双缓冲。为此,您需要创建BufferedImage并从中获取Graphics。将所有内容绘制到图像上,将图像渲染到屏幕上,然后最终使用背景颜色或图像填充图像以重置图像。

样品:

//one time instantiation
BufferedImage b = new BufferedImage(width, height, mode);

paint(Graphics g)

Graphics buffer = b.getGraphics();
//render all of the stuff on to buffer
Graphics2D g = (Graphics2D) buffer;
    for (Ball ball : Ball.BALLS) {
        g.drawOval((int) ball.getLocation().getX(), (int) ball.getLocation().getY(), ball.getRadius(),  ball.getRadius());
    }
g1.drawImage(b, 0, 0, width, height, null);
g.setColor(Color.BLACK);
//reset the image
g.drawRect(0, 0, width, height);
g.dispose();