我正在使用youtube上的视频教程编写Java代码来制作Java游戏applet。但是,教师并没有真正解释applet的更新方法如何在他调用时进行双缓冲。
import java.awt.*; import java.applet.Applet; public class Game extends Applet implements Runnable { private Image i; private Graphics g2; private int x, y, dx = 1, dy = 1, radius = 10; ... public void update(Graphics g) { if ( i == null ) { i = createImage(getHeight(), getHeight()); } g2 = i.getGraphics(); g2.setColor(getBackground()); g2.fillRect(0, 0, getWidth(), getHeight()); g2.setColor(getForeground()); paint(g2); g.drawImage(i, 0, 0, null); } public void paint(Graphics g) { x+= dx; y+= dy; g.setColor(Color.RED); g.fillOval( x, getHeight() - y, radius * 4, radius * 4); g.setColor(Color.BLUE); g.fillOval( getWidth() - x - radius, y, radius * 4, radius * 4); g.setColor(Color.GREEN); g.fillOval( x, y, radius * 4, radius * 4); g.setColor(Color.YELLOW); g.fillOval( getWidth() - x , getHeight() - y , radius * 4, radius * 4); }
这里是如何消除闪烁的?拥有Image对象有什么用?有另一个Graphics对象有什么用,为什么不使用参数Graphics?
答案 0 :(得分:4)
双缓冲的一般想法是绘图很慢,如果你有很多东西要绘制,用户会以闪烁的形式注意到这一点。相反,您将所有绘图都设置为屏幕外图像(缓冲区)。然后,当您准备好时,您交换屏幕外缓冲区,以便它现在在屏幕上绘图。这种交换很快发生,因为它通常只是更新指针。
用户不再看到闪烁,因为所有绘图工作都在屏幕外完成。
您发布的代码是双缓冲的变体。所有绘图工作都在屏幕外完成到Image对象i
。绘图完成后,图像对象将被复制到update
方法的最后一行中的组件。
我说变种是因为上面的代码没有交换缓冲区。而是将屏幕外缓冲区i
复制到屏幕缓冲区Graphics
。它仍然消除了闪烁,因为所有渲染工作都在屏幕外完成。复制图像仍然非常快。
第二个g2
对象存在,因为在绘制时应始终使用组件提供的对象。因此,上面的代码询问Image对象的Graphics对象。但是,没有真正的理由将update
存储为成员变量,您每次只能在{{1}}中请求它。