我一直试图在我的游戏库中实现双缓冲,但它比没有它时显着慢。
这是我实现它的类。基本上,它绘制到图像上,然后将图像绘制到JPanel的图形上(pg)。
public abstract class DrawingPanel extends GameLoop {
private BufferedImage image;
private Graphics2D ig;
private Graphics pg;
private int backgroundRGB;
public DrawingPanel(final int fps, final int ups, final JPanel panel, final Color background) {
super(fps, ups);
initialize(panel, background);
}
/**
* Creates a panel with 60 fps and 120 ups
*
* @param panel
* @param background
*/
public DrawingPanel(final JPanel panel, final Color background) {
this(60, 120, panel, background);
}
public DrawingPanel(final JPanel panel) {
this(panel, Color.WHITE);
}
public DrawingPanel(final int ups, final JPanel panel, final Color background) {
super(ups);
initialize(panel, background);
}
private void initialize(final JPanel panel, final Color background) {
image = GraphicsUtils.createImage(panel.getWidth(), panel.getHeight(), Transparency.OPAQUE);
ig = (Graphics2D) image.getGraphics();
pg = panel.getGraphics();
GraphicsUtils.prettyGraphics(ig);
backgroundRGB = background.getRGB();
panel.addMouseListener(this);
panel.addMouseMotionListener(this);
panel.addKeyListener(this);
panel.addMouseWheelListener(this);
panel.setFocusable(true);
panel.requestFocusInWindow();
}
@Override
public void draw() {
// set background
Arrays.fill(((DataBufferInt) image.getRaster().getDataBuffer()).getData(), backgroundRGB);
// draw on the buffer
draw(ig);
// draw our buffer to the screen
pg.drawImage(image, 0, 0, null);
}
public abstract void draw(Graphics2D g);
}
结果: 这意味着25% - 6%= 19%的时间仅用于绘制方法!
我认为可能是因为我使用Array.fill
,但事实证明这不是一个无用的过早优化;"如果我用
ig.setColor(backgroundColor);
ig.fillRect(0, 0, image.getWidth(), image.getHeight());
花费的时间甚至更长:26 - 5%= 21%。有什么方法可以加速这种方法吗?
顺便说一下,GraphicsUtils.createImage
会从我的GraphicsConfiguration
创建一个兼容的图片。
如果您想查看整个代码,整个库都是on github。
答案 0 :(得分:1)
这不是绘画在Swing中的作用 - > pg = panel.getGraphics();
这是一个非常糟糕的主意。你正在Swing的被动渲染引擎和你试图绘制一个快照和#34;组件。
当您正确使用Swing组件时,内部双重缓冲,但是,您需要使用API。
首先查看Performing Custom Painting和Painting in AWT and Swing,了解有关绘画如何在Swing中工作的详细信息
基本上,正在发生的事情是,您使用getGraphics
的结果绘制到面板,RepaintManager
即将出现并决定是否需要更新您的组件并重新绘制它,生成一个空白面板,重复非常快。这就是造成你闪烁的原因。在Swing中,您不能控制绘制过程,您只能要求在绘制周期发生时通知(例如覆盖paintComponent
)并向绘画系统请求重绘应该发生,但它&#39 ;直到油漆系统,实际决定何时发生油漆循环。
相反,首先要覆盖面板的paintComponent
方法,然后在其中执行所有自定义绘制。使用repaint
请求更新组件。
如果你真的"需要一个活跃的绘画过程,然后查看BufferStrategy
和BufferStrategy and BufferCapabilities,它为您提供了直接控制何时将输出推送到屏幕设备的方法。