使用双缓冲区
|
|
Author: 一滴蔚蓝色 | Date: 2008-03-01 |
View: 859 |
开发技术 - 程序设计 | Digg:
0
|
|
作者:潇潇 出处:www.j2mefans.com 该文章为本站原创,如有引用,请注明出处和作者 为什么要使用双缓冲区?通过前面的学习我们知道当要绘制屏幕时,我们只要调用paint函数即可。其中我们可以使用绘图方法来绘制任何文字图形图像。可是 当我们绘制的东西多了之后,你就会发现又是屏幕上的显示根本不是我们要的结果,很杂乱。细想想,会知道因为paint函数中,我们是一边绘制一边显示,所 以当内容过多,就会产生没绘制完成,就显示到屏幕上的结果。 因此,双缓冲区就提供了一个完美的解决方案。我们可以在缓冲区2中绘制图像,而是用缓冲区1来输出到屏幕。这样我们就可以控制绘制和现实的过程,从而避免上面的现象。 对于MIDP2.0来说,因为GameCanvas类本身带有双缓冲区的功能,所以我们在代码中可以看到这样的结构: //这里添加对屏幕的绘制 public void paint(Graphics g) { // 清除屏幕 g.setColor(0xffffffff); g.fillRect(0, 0, getWidth(), getHeight()); //绘制屏幕 g.setColor(0,0,0); g.fillRect(x,y,20,20); // 刷新屏幕缓冲区 flushGraphics(); } 通过代码我们可以知道绘制屏幕部分,并不是直接在屏幕上绘制,而是现在一个和屏幕一般大小的内存中绘制,在通过flushGraphics函数输出到屏幕的。 但对MIDP1。0就没那么简单了。我们必须显示的创建一个和屏幕相当的内存区,在其中绘制图像,完成后,通过输出该缓冲区图像来绘制屏幕。典型的代码: private Image offScreenBuffer; //定义屏幕缓冲区 public OCanvas() { …… //在画布的构造函数或者start函数中添加下面代码 initResources(); } Private void initResources() { //创建屏幕缓冲区 offScreenBuffer = Image.createImage(getWidth(),getHeight()); } Protected void paint(Graphics g) { //在下面的函数中绘制图形 renderWorld(); //使用下面的语句来输出屏幕缓冲区到屏幕上 graphics.drawImage(offScreenBuffer,0,0,Graphics.LEFT|Graphics.TOP); } 这样我们就可以在initResources函数中,初始化绘图变量,在renderWorld函数中真正进行绘制。 下面是一段例程: /** * 文件名:Ocanvas.java * 画布类 */ import javax.microedition.lcdui.*; import java.io.*; import java.util.*; import java.lang.Thread; public class OCanvas extends Canvas implements Runnable { //定义变量 private Display display; private boolean sleeping; private long frameDelay; //双缓冲区 private Image offScreenBuffer; private int XSpeed,YSpeed; private int x,y; private static int statusLineHeight = 10; private int laneHeight = 0; private static final int topMargin =3 ; public OCanvas(Display d) { //类构造函数,初始化类变量 super(); display = d; // 设置帧频 (30 fps) frameDelay = 33; } void start() { // 设置这个画布为当前屏幕 display.setCurrent(this); // 初始化一些游戏中的变量,载入相关图片 x=getWidth()/2-10; y=getHeight()/2-10; //建立双缓冲区 initResources(); // 开始动画线程 sleeping = false; Thread t = new Thread(this); t.start(); } private void initResources() { offScreenBuffer = Image.createImage(getWidth(), getHeight()); int heightMinusStatus = getHeight()- statusLineHeight; laneHeight = ((heightMinusStatus)/9); } public void stop() { // 停止动画线程 sleeping = true; } public void run() { // 动画线程开始后运行 // 主游戏循环 while (!sleeping) { //更新屏幕显示 repaint(); //线程休眠 try { Thread.sleep(frameDelay); } catch (InterruptedException ie) {} } } //这里添加对屏幕的绘制 public void paint(Graphics g) { // 清除屏幕 g.setColor(0xffffffff); g.fillRect(0, 0, getWidth(), getHeight()); // 重绘屏幕 renderWorld(); g.drawImage(offScreenBuffer,0,0,Graphics.LEFT | Graphics.TOP); } private void renderWorld() { Graphics osg = offScreenBuffer.getGraphics(); int y1=0; //绘制路边 osg.setColor(0x00209020); y1+=(laneHeight)+topMargin; osg.fillRect(0,0,getWidth(),y1); //绘制边线 osg.setColor(0x00808080); osg.drawLine(0,y1-2,getWidth(),y1-2); osg.setColor(0x00000000); osg.drawLine(0,y1-1,getWidth(),y1-1); //绘制马路 osg.setColor(0x00000000); osg.fillRect(0,y1,getWidth(),laneHeight *3); //绘制马路线 osg.setStrokeStyle(Graphics.DOTTED); osg.setColor(0x00AAAAAA); y1+= laneHeight; osg.drawLine(0,y1,getWidth(),y1); y1+= laneHeight; osg.drawLine(0,y1,getWidth(),y1); y1+= laneHeight; osg.drawLine(0,y1,getWidth(),y1); //绘制中间马路 osg.setColor(0x00666666); osg.fillRect(0,y1-2,getWidth(),2); osg.setColor(0x00aaaaaa); osg.fillRect(0,y1,getWidth(),laneHeight); y1+=laneHeight; osg.setColor(0x00666666); osg.fillRect(0,y1-2,getWidth(),2); //绘制马路 osg.setColor(0x00000000); osg.fillRect(0,y1,getWidth(),laneHeight *3); //绘制马路线 osg.setStrokeStyle(Graphics.DOTTED); osg.setColor(0x00AAAAAA); y1+= laneHeight; osg.drawLine(0,y1,getWidth(),y1); y1+= laneHeight; osg.drawLine(0,y1,getWidth(),y1); y1+= laneHeight; osg.drawLine(0,y1,getWidth(),y1); osg.setStrokeStyle(Graphics.SOLID); osg.setColor(0x00808080); osg.drawLine(0,y1,getWidth(),y1); y1++; osg.setColor(0x00000000); osg.drawLine(0,y1,getWidth(),y1); //绘制路边 osg.setColor(0x00209020); osg.fillRect(0,y1,getWidth(),y1+(laneHeight)+topMargin); //绘制方块 osg.setColor(255,255,255); osg.fillRect(x,y,20,20); } //处理按键信息 public void keyPressed(int keyCode) { int keystates = getGameAction(keyCode); switch(keystates) { case UP: y = Math.max(0, y - 2); break; case DOWN: y = Math.min(getHeight()-20, y + 2); break; case LEFT: x = Math.max(0, x - 2); break; case RIGHT: x = Math.min(getWidth(), x + 2); break; } } } 更多阅读: |
尚无评论发表