这几天一直纠结游戏界面的淡入淡出怎么实现。之前终于了解可以用AlphaComposite修改图片的alpha值,加以延时可以实现淡入淡出,但界面闪得很厉害。
之前做图形编程的时候也知道,这是图片没有绘制完成然后显示到屏幕的原因。什么意思呢?就比方说一个运动的小球,实现的效果是先画小球,然后擦除,然后在新位置重绘小球。显然,擦除是不应该被显示到屏幕上的。小球到重绘的时候再显示到屏幕才是。曾经用过OpenGL写过一个2.5D的游戏,也要用到双缓冲,可那时候用的双缓存就一个API函数就搞定了。现在要在Java swing上实现双缓存消除闪烁应怎么做呢?
在Java swing中,绘制的原理如下:
update() -> paint(Graphics g) -> paintComponent(Graphics g)
它们是逐渐调用的,Java swing内置有双缓冲,在paint(Graphics g)中。
假如我们的图像绘制在JPanel上,我们可以继承JPanel,然后复写里面的paintComponent(Graphics g)和update方法。我们可以在paintComponent上绘制图像,然后调用paint方法就可以调用paintComponent方法绘制图像。
双缓冲的实现:
复写JPanel类中的update()方法,新建一个图像缓存空间,然后把它的画笔拿过来,用paint方法把要绘制的东西绘制上去。再一次性把图像显示在JPanel控件上。
public class MyPane extends JPanel {
private Image image; //你要绘制的图形
private Image offScreenImage; //图形缓存
public MyPane(Image img) {
this.image = img;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
//................
//.........你要绘制的东西
}
public void update(Graphics g) {
if(offScreenImage == null)
offScreenImage = this.createImage(800, 600); //新建一个图像缓存空间,这里图像大小为800*600
Graphics gImage = offScreenImage.getGraphics(); //把它的画笔拿过来,给gImage保存着
paint(gImage); //将要画的东西画到图像缓存空间去
g.drawImage(offScreenImage, 0, 0, null); //然后一次性显示出来
}
public void animation() {
try { //延时,然后调用update(getGraphics),更新画面
Thread.sleep(15);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
update(getGraphics());
}
}