重新绘制时闪烁的特定对象

时间:2017-01-08 19:59:30

标签: java graphics awt flicker

这个问题不是“整个屏幕闪烁”类型的问题。

我正在尝试理解Java图形并制作一个简单的游戏,但是当用新对象重新绘制场景时,一些对象会一直闪烁, odly 而不是整个屏幕

这是我的render()方法:

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

private void render() {
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null){
            createBufferStrategy(6);
            return;
        }
        Graphics g = bs.getDrawGraphics();
        Graphics2D g2d = (Graphics2D)g;
        //fill screen with black background
        g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
        //draw cool stuff
        try {
            for (int i = 0; i < Element.elements.size(); i++) {
                Element.elements.get(i).render(g2d);
            }
        } catch (Exception e) {
            System.err.println("No such element to render");
        }
        //dispose graphics
        g.dispose();
        g2d.dispose();
        bs.show();
}

什么可能导致这个问题?我不认为大量的气泡会导致这个问题。

如果你想结账,这是项目zip file,和 这是.jar file

1 个答案:

答案 0 :(得分:2)

您的模型更新(在鼠标移动时在事件线程中完成)需要与渲染线程同步。闪烁发生是因为渲染发生时模型有时处于不一致状态。

解决此问题的一种方法是在线程中渲染您正在更新模型。您可以在事件线程中使用SwingUtilities运行渲染:

try {
    SwingUtilities.invokeAndWait(new Runnable() {
        @Override
        public void run() {
            render();
        }
    });
} catch (InvocationTargetException | InterruptedException e) {
    running = false;
    System.err.println("Render interrupted");
}

如果您正在使用由AWT或Swing呈现的组件,那么总是在事件线程中进行渲染。

当您自己控制整个渲染过程时,您可以选择在单独的线程中进行渲染,但是您必须同步对模型的访问(即,应该同步对事件线程执行的模型的写入使用渲染线程执行的读取。

例如:

Shredder.scan()中(从事件线程调用)

public static void scan() {
    synchronized (Element.elements) {
        for (Element element : Element.elements) {
            if (element.containsMouse()) {
                if (element.getSize() < 24) {
                    Element.elements.remove(element);
                } else {
                    element.cloneItself();
                    Element.elements.remove(element);
                }
                skip = true;
                break;
            }
        }
    }
}

在你的渲染线程中:

synchronized (Element.elements) {
    for (int i = 0; i < Element.elements.size(); i++) {
        Element.elements.get(i).render(g2d);
    }
}

作为一种形式,将需要同步的代码放在一个位置是个好主意,这样调用代码就不必关心保持一致性。