J2ME游戏开发中的双缓冲技术
2012-07-24 00:39
134 查看
双缓冲的原理:
在手机游戏开发中,可能一个完整的游戏界面需要很多图像的绘制,而在绘制过程中手机屏幕需要不断显示,如果该界面的游戏图像元素太多,很可能当前帧还没有绘制完成下一帧的绘制任务就已经开始,这样会导致屏幕的闪烁。为了解决这一个问题,我们可以使用一种叫做“双缓冲”的方法来解决该问题。各个手机厂商可以从硬件上支持双缓冲,这样在显示屏幕绘图之前,可以使用一个图像内存来进行屏幕外绘图,等到这个图像内存将整个界面的所有元素在后台绘制完成后,在使用另外一个图像内存来将这个屏幕外的图像绘制到实际屏幕上,这样,整个界面的所有元素好像是一张图。屏幕外的图像内存和屏幕内的图像内存如此交叉绘图,就避免了图像闪烁的产生。
如果手机本身不支持双缓冲功能,在设计时可以通过可变图像来自行设计双缓冲绘图。方法是:在屏幕外内存中创建一个可变图像,一次游戏循环中的所有绘图任务都绘制到该可变图像中,当所有绘图任务完成后,一次性将屏幕内存中的可变图像绘制到屏幕,如下图所示:
从上图中可以看出,当发生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(); } } }
结果如下图所示:
相关文章推荐
- J2ME游戏开发之按钮事件
- J2ME 拼图游戏 快速开发 全过程 之代码祥解(2 )——游戏数据库与游戏模型开发
- j2me游戏开发之LWJGL(Lightweight Java Game Library)
- 用Eclipse开发J2ME手机游戏 第五讲 J2ME应用程序的仿真机发布
- j2me游戏开发之手机键值
- J2ME游戏开发中的地图设计与绘制
- J2ME游戏开发之层:动画
- 开发易于移植的J2ME游戏
- J2ME游戏开发
- 从J2ME学Symbian游戏开发(一)
- 从J2ME学Symbian游戏开发(一)
- 【Android游戏开发二十二】(图文详解)游戏中灵活实现动画播放!简述J2me的游戏类库与Android游戏开发!
- JAVA游戏编程之二----j2me MIDlet 手机游戏入门开发--扫雷(3)-带线程--仿windows扫雷
- J2ME游戏开发技巧
- J2ME游戏开发中时钟的简单实现
- J2ME游戏开发之图片绘制
- 使用J2ME技术开发《贪吃蛇》游戏(已在《软件报》发表,严禁转载)
- Eclipse开发J2ME程序 第六讲 制作图形化手机游戏
- J2ME游戏开发实例讲解
- 开发易于移植的J2ME游戏