`
duoerbasilu
  • 浏览: 1482062 次
文章分类
社区版块
存档分类
最新评论

J2ME游戏开发中的双缓冲技术

 
阅读更多

双缓冲的原理:

在手机游戏开发中,可能一个完整的游戏界面需要很多图像的绘制,而在绘制过程中手机屏幕需要不断显示,如果该界面的游戏图像元素太多,很可能当前帧还没有绘制完成下一帧的绘制任务就已经开始,这样会导致屏幕的闪烁。

为了解决这一个问题,我们可以使用一种叫做“双缓冲”的方法来解决该问题。各个手机厂商可以从硬件上支持双缓冲,这样在显示屏幕绘图之前,可以使用一个图像内存来进行屏幕外绘图,等到这个图像内存将整个界面的所有元素在后台绘制完成后,在使用另外一个图像内存来将这个屏幕外的图像绘制到实际屏幕上,这样,整个界面的所有元素好像是一张图。屏幕外的图像内存和屏幕内的图像内存如此交叉绘图,就避免了图像闪烁的产生。

如果手机本身不支持双缓冲功能,在设计时可以通过可变图像来自行设计双缓冲绘图。方法是:在屏幕外内存中创建一个可变图像,一次游戏循环中的所有绘图任务都绘制到该可变图像中,当所有绘图任务完成后,一次性将屏幕内存中的可变图像绘制到屏幕,如下图所示:

从上图中可以看出,当发生n次绘图时,传统的直接绘图方式会在屏幕上直接“擦除--重绘”n次,因此发生闪烁;双缓冲绘图方式是将n次所要绘制的内容绘制到屏幕外内存的可变图像中,完成后一次性绘制到屏幕上,因此画面不会闪烁。

双缓冲的具体实现方法:

了解了上面所讲解的双缓冲原理之后,就可以使用可变的Image图像来进行设计。在双缓冲设计中,可以使用Canvas类中的isDoubleBuffered()方法来检测手机设备是否支持双缓冲。如果支持,则不必使用双缓冲,否则就使用双缓冲;另外通过Image的getGraphics()方法,该方法可用于获取可变图像的画笔Graphics,然后用该Graphics在可变图像中绘图。

MainMIDlet类:

import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;


public class MainMIDlet extends MIDlet {

	public MainMIDlet() {
		Display.getDisplay(this).setCurrent(new MyCanvas());
	}
	public void exit(){
		try {
			destroyApp(true);
		} catch (MIDletStateChangeException e) {
			e.printStackTrace();
		}
		notifyDestroyed();
	}

	protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
		// TODO Auto-generated method stub

	}

	protected void pauseApp() {
		// TODO Auto-generated method stub

	}

	protected void startApp() throws MIDletStateChangeException {
		// TODO Auto-generated method stub

	}

}

MyCanvas类:

import java.io.IOException;

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

//双缓冲:解决屏幕抖动的问题
public class MyCanvas extends Canvas {
	private Image off_screen;//后台屏幕(可变图像)
	private Graphics off_g;//后台屏幕画笔
	private Image backg;
	private Image cock1,cock2,cock3,cock4;
	private static int SW,SH;//屏幕宽高
	public MyCanvas() {
		this.setFullScreenMode(true);
		off_screen = Image.createImage(this.getWidth(), this.getHeight());//生成后台屏幕
		off_g = off_screen.getGraphics();//得到后台画笔
		try {
			backg=Image.createImage("/map1.png");
			cock1=Image.createImage("/cock1.png");
			cock2=Image.createImage("/cock2.png");
			cock3=Image.createImage("/cock3.png");
			cock4=Image.createImage("/cock4.png");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		new MyThread().start();
	}

	protected void paint(Graphics g) {//g:前台画笔
		g.drawImage(off_screen, 0, 0, 20);
	}

	public void render(){
		this.setFullScreenMode(true);
		SW=this.getWidth();
		SH=this.getHeight();
		off_g.setColor(0xff000000);
		off_g.fillRect(0, 0, off_screen.getWidth(), off_screen.getHeight());
		off_g.drawImage(backg, 0, 0, Graphics.LEFT|Graphics.TOP);
		off_g.drawImage(cock1, 0, 0, Graphics.LEFT|Graphics.TOP);
		off_g.drawImage(cock2, SW, 0, Graphics.RIGHT|Graphics.TOP);
		off_g.drawImage(cock3, 0, SH, Graphics.LEFT|Graphics.BOTTOM);
		off_g.drawImage(cock4, SW, SH, Graphics.RIGHT|Graphics.BOTTOM);
	}
	
	private class MyThread extends Thread{
		public void run(){
			while(true){
				long start = System.currentTimeMillis();
				render();
				repaint();//发出(重绘请求),UI线程负责回调paint方法
				long end = System.currentTimeMillis();
				System.out.println("绘制屏幕花费的时间:"+(end-start));
				if (end - start < 30) {// 使FPS(Frame Per Second)尽量平缓
					sleepGame(30 - (end - start));
				} else {
					sleepGame(1);
				}
			}
		}
		
	}
	public void sleepGame(long time) {
		try {
			Thread.sleep(time);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}


结果如下图所示:

分享到:
评论

相关推荐

    Android游戏开发之旅.doc

    今天Android123开始新的Android游戏开发之旅系列,主要从控制方法(按键、轨迹球、触屏、重力感应、摄像头、话筒气流、光线亮度)、图形View(高效绘图技术如双缓冲)、音效(游戏音乐)以及最后的OpenGL ES(Java层)和NDK...

    java源码包2

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    java源码包---java 源码 大量 实例

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    java源码包3

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    java源码包4

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    J2ME优化压缩PNG文件 4个目标文件 内容索引:JAVA源码,综合应用,J2me游戏,PNG,图形处理 这是个J2ME控制台程序,它能剔除PNG文件中的非关键数据段,减少文件大小从而达到压缩图片的目的。而图片的质量并不会受到损失...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    J2ME优化压缩PNG文件 4个目标文件 内容索引:JAVA源码,综合应用,J2me游戏,PNG,图形处理 这是个J2ME控制台程序,它能剔除PNG文件中的非关键数据段,减少文件大小从而达到压缩图片的目的。而图片的质量并不会受到损失...

    JAVA上百实例源码以及开源项目

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    JAVA上百实例源码以及开源项目源代码

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    嵌入式Linux程序设计案例与实验教程-实例代码

    第1章 Linux开发基础.1 1.1 Linux系统概述1 1.1.1 Linux简介1 1.1.2 Linux系统的特点1 1.1.3 Linux系统的组成2 1.2 Linux系统的使用2 实验1.1 熟悉Linux基本命令与文件目录系统2 1.3 全屏幕编辑器与vi...

    嵌入式Linux程序设计案例与实验教程(配套光盘)第三部分

    第1章 Linux开发基础.1 1.1 Linux系统概述1 1.1.1 Linux简介1 1.1.2 Linux系统的特点1 1.1.3 Linux系统的组成2 1.2 Linux系统的使用2 实验1.1 熟悉Linux基本命令与文件目录系统2 1.3 全屏幕编辑器与vi6 ...

    嵌入式Linux程序设计案例与实验教程(配套光盘)第二部分

    第1章 Linux开发基础.1 1.1 Linux系统概述1 1.1.1 Linux简介1 1.1.2 Linux系统的特点1 1.1.3 Linux系统的组成2 1.2 Linux系统的使用2 实验1.1 熟悉Linux基本命令与文件目录系统2 1.3 全屏幕编辑器与vi6 ...

    嵌入式Linux程序设计案例与实验教程(配套光盘)第一部分

    第1章 Linux开发基础.1 1.1 Linux系统概述1 1.1.1 Linux简介1 1.1.2 Linux系统的特点1 1.1.3 Linux系统的组成2 1.2 Linux系统的使用2 实验1.1 熟悉Linux基本命令与文件目录系统2 1.3 全屏幕编辑器与vi6 ...

Global site tag (gtag.js) - Google Analytics