DoubleBuffer 实现

     绘制地图的时候会出现图片断裂,屏幕闪烁等绘图效率问题, 怎么办?双缓冲技术。实际上,在midp1.0中没有game包,也没有实现双缓冲。但有些设备本身就支持双缓冲(midp2.0自动实现了双缓冲),每次都是先把屏幕重画在缓冲之中,然后再绘制在显示屏幕上,而不是直接绘制在显示屏幕上。如果Canvas类下的DoubleBuffered()返回true, 则表示设备已实现了双缓冲。

    造成屏幕闪烁的主要原因在于,画面在显示的同时程序又在改变它,于是画面闪烁。解决办法是在内存中开辟一片区域作为后台画面,程序对它更新、修改,完成后再显示它。这样被显示的图像永远是已经完全画好的图像,程序修改的将不是正在被显示的图像。

 

     原理:把电脑屏幕看作一块黑板。首先我们在内存环境中建立一个“虚拟“的黑板,然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候,再一次性的把内存中绘制好的图形“拷贝”到实际的黑板(屏幕)上。即先在一个图片(可变图像:可以很好的用作屏幕外缓冲)上进行paint()得操作,当完成了以后就把它copy到屏幕上,由于通常copy得时候速度很快就不会出现闪烁了。
     具体过程:按屏幕大小建立一个缓冲对象bufferImage(必须是可变Image);然后Graphics g = bufferImage.getGraphics(),最后用g绘制图片到缓冲对象bufferImage中,将所有的绘制都放在可变图像中;最后通过repaint()调用paint(Graphics g)将缓冲对象bufferImage绘制到真实屏幕上。

 

package forrest.doublebuffer;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

/**
 * 实现双缓冲的Game画布。实现原理是创建一个BufferImage。然后绘制,最后显示出来。就这么简单。
 */
public abstract class DoubleBuffer extends Canvas {
	private Image bufferImage; // 绘制缓冲的图片,即黑板。用户绘制资源的时候都是操作这个图片来进行的。
	private int clipX, clipY, clipWidth, clipHeight;
	private boolean isSetClip;
	
	protected DoubleBuffer() {
		bufferImage = Image.createImage(getWidth(), getHeight());
	}
	
	protected void paint(Graphics g) {
		// 对指定区域进行DoubleBuffer
		if (isSetClip) {
			g.clipRect(clipX, clipY, clipWidth, clipHeight);
			isSetClip = false;
		}
		g.drawImage(bufferImage, 0, 0, Graphics.TOP | Graphics.LEFT);
	}
	
	public void flushGraphics() {
		repaint();
		serviceRepaints();
	}
	
	public void flushGraphics(int x, int y, int w, int h) {
		isSetClip = true;
		clipX = x;
		clipY = y;
		clipWidth = w;
		clipHeight = h;
		
		repaint();
		serviceRepaints();
	}
	
	/**
	 * Designer will get the picture through invoking this method, then paint this picture.
	 * */
	protected Graphics getGraphics() {
		return bufferImage.getGraphics();
	}
	
	/**
	 * For nokia platform,when user invoke setFullScreenMode(boolean enable), create 
        * new buffered picture based on parameter: w and h.
	 * */
	protected final void sizeChanged(int w, int h) {
		if (h > getHeight()) {
			bufferImage = Image.createImage(w, h);
		}
	}
}

 

package forrest.doublebuffer;

import java.io.IOException;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public class DoubleBuffer extends Canvas {
	private Image bufferImage, //mutable picture,作为绘制缓冲
				  img; // 不变picture,用来load图片文件
	public DoubleBuffer() throws IOException {
		img = Image.createImage("/img.png");
		bufferImage = Image.createImage(getWidth(), getHeight()); // 用一个mutable picture作为绘制缓冲
		Graphics g = bufferImage.getGraphics();
		g.setColor(0xffffff);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.drawImage(img, getWidth() / 2, getHeight() / 2, Graphics.VCENTER | Graphics.HCENTER);
	}
	protected void paint(Graphics g) {
		g.drawImage(bufferImage, 0, 0, Graphics.TOP | Graphics.LEFT); // g: 屏幕画笔,将缓冲区上的内容绘制到屏幕上
	}
	
}

 

package forrest.doublebuffer;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public class DoubleBuffer extends Canvas {
	private Image bufferImage;
	
	public DoubleBuffer() {
		if (!isDoubleBuffered()) {
			bufferImage = Image.createImage(getWidth(), getHeight());
		}
	}
	
	protected void paint(Graphics g) {
		Graphics temp = g;
		if (bufferImage != null) {
			g = bufferImage.getGraphics();
		}
		g.setColor(0xff0000);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.setColor(0xffffff);
		g.drawLine(0, 0, 100, 100);
		if (g != temp) {
			// 把bufferImage直接copy到屏幕上
			temp.drawImage(bufferImage, 0, 0, Graphics.TOP | Graphics.LEFT);
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值