科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道[冷枫]一个老菜鸟的J2ME心得

[冷枫]一个老菜鸟的J2ME心得

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

一个老菜鸟的J2ME心得,写的不好海涵呀。希望一起多多加油,在J2ME的大海洋里一起捡点稍亮点的贝壳,装扮下自己的人生。

作者:冷枫 来源:CSDN 2007年9月23日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共2页)

在绘制某一个屏幕区域过于频繁的情况下(譬如动画效果),难免会发生“闪烁”的现象,造成这一问题的原因就在于在绘制屏幕某处之后的瞬间程序又在此处绘制了新的图像,解决这一现象比较有效的方法就是绘制缓冲图像,在内存开辟一块区域作为后台画面,游戏逻辑对它更新,在一次循环结束后再显示,这样就可以在避免出现因一次循环中对画面进行多次更新而产生的闪烁现象,另外请特别注意你在repaint中设定好的矩形范围。

具体的操作方法如下:

public class MyCanvas extends Canvas implements Runnable

{

 Graphics bg;            //缓冲区图像设备

 Image buf;              //缓冲区图像

 public MyCanvas()

 {

  ......

drawOthers();

  int height = getHeight();

  int width = getWidth(); 

  buf = Image.createImage(width, height); //按显示屏幕大小建立缓冲对象

                                      //此处也可以设为重复绘制的矩形区域 

  //将缓冲图像的图形设备赋给bg

  bg = buf.getGraphics();

  ......

 } 

 

 public void run()

 {......

  for(i=0;i<ROWS;i++)

  {

   for(j=0;j<COLS;j++)

   {

    drawBlock(x,y);//在缓冲区内绘制图像

   }

  }

  repaint();//将缓冲区的图像重绘到屏幕上

 }

 private void drawBlock(int block_x, int block_y)

 {  

  //取得方块的坐标

  int x = getLeft(block_x);

  int y = getTop(block_y);

  //取得方块的颜色

  int c= board[block_x][block_y];  

  bg.drawImage(imgs[c], x, y, Graphics.TOP | Graphics.LEFT); //在缓冲区的图                            形设备中循环绘制图像

 }

 

 public void paint(Graphics g)

 {

  g.drawImage(buf, 0, 0, Graphics.TOP | Graphics.LEFT); //绘制缓冲区图像

 }

}

    我在游戏中的地图就是采用这种方法来绘制的。

闪屏和进度条

你的程序有时候会由于处理一些比较复杂的工作(尤其是初始化)而导致整个屏幕静止了下来,不耐烦的用户就开始使劲的揿手机的键盘了。毕竟是手机程序嘛,如果让用户看到游戏的显示已经停止了变化,他们就一定会怀疑游戏或者手机发生了故障。所以我们要想办法告诉用户当前程序正在运行,这就涉及到了延迟掩盖技术。方法有很多,最常用的是闪屏(Splash Screen)和进度条方法。

 

如果你的游戏不能迅速的反应出用户的按键操作,则会被感应到响应迟钝。其实这种响应的速度与不同型号的手机是有很大关系的。当然了,任何超过一秒的操作都会被用户认为是极为漫长的,所以无论是何种型号的手机,都必须要确保按键事件回调函数(keyPresscommandAction)的快速返回。因为负责重绘的线程可能也会调用按键函数(而重绘线程又往往是最耗时的),所以应该启动一个独立的线程,让用户看到他的操作有所回应。

 

多线程被认为是解决此问题的一个合适的方法。这是因为当你的一个线程正处于某种条件等待的时候,另一个线程仍然能工作。需要注意的是,Java线程不一定会具有抢先权,所以我们的代码不应该在死循环中去等待条件,这样常会被用户错误地认为是死机了。遇到实时性比较高的游戏我们可以在每次的循环中调用yield或者wait方法。

例如:

while (!stopped)

  {

doSomething();

synchronized(this)

  {

wait(500); //milliseconds, i.e. half a second

}

}

 

 

 使用资源

合理的资源利用,也是保证程序高效的有效手段之一。其中最为主要的就是合理使用你的堆内存,必须确保释放不再需要的FormCanvas,(例如Splash Screen,游戏的关卡等)这些可都是些大家伙,极耗内存的,不用的时候可以将他们置为空,以便进行垃圾收集。不经常用的屏幕(如游戏说明,选项等)应该在用的时候才创建,并且在使用后别忘了作为垃圾收回。这样做也是牺牲了速度而换取了额外的堆空间。如何在时间和空间这对矛盾中进行取舍,可就要完全看读者你了。J

我们在写java文件的时候,经常要导入一些开发包,这些开发包给我们提供了各种各样的支持的库功能。譬如系统自带的 java.io.*或者 java.util.* 以及第三方厂商提供的扩充包com.nokia.mid.ui.FullCanvas等。但是如果整个库都被包括在Midlet文件中,你可能就要为许多程序本不需要的功能增加系统开销了。所以在使用库的时候,一定要清楚是否真正的需要用到库中所有的类。请尽量不要使用.*的模式,而是明确地指定您具体导入的包名称,例如com.nokia.mid.ui.FullCanvas

在垃圾的对象负责收集管理的实例中,我不知道有什么比StringStringBuffer更加有名气的了。不止在一份资料上有这方面的例子。String 作为一个不可变对象,他的状态自创建后就不可改变了。这样虽然利于代码的可靠和线程的安全,但是当它所代表的值发生变化时,初始值就失去了意义,于是旧的对象滞留在了堆里,形成垃圾。多数程序员都应记得曾因为使用String而产生了不知道多少的垃圾对象,这对程序的效率会有很大影响的。所以要想进一步提高效率,最好使用可重用的对象。

    示例代码如下:

经典的例子是字符串的连接。

请看下面的倒排字符串函数:

static String reverse(String s)

{

String t = "";

for (int i = s.length()-1; i >= 0; --i)

t += s.charAt(i);

    return t;

}

5行的赋值语句并不改变字符串t,因为t是不可变的。相反,它每次都创建一个新字符串,复制现存的值并添加新字符。这一方法将不必要地创建s.length()个垃圾对象。这个典型例子说明了不可变对象所存在的问题。然而,对于字符串却有一个简单的解决办法:类java.lang.StringBuffer是与String相对应的的可变操作类,上面的例子可以更高效地重写为:     static String reverse(String s)

{

StringBuffer t = new StringBuffer(s.length());

for (int i = s.length()-1; i >= 0; --i)

t.append(s.charAt(i));

return t.toString();

}

这是一个经常被拿出来的范例。J

 

 

试程序

我在开发中是选用WTK环境来进行编译打包的。写Code采用的是Uedit。这些工具配置起来极为简单,使用也很方便。可就是有一样,调试起来比较的困难,没有一个很好的DeBug工具。尽管WTK自带了根据设备定制异常跟踪、内存管理等功能,但用于调试程序还是不太方便。故此需要我们自己来想想办法。最经常用的当然是ShowMessage大法了,可以自己在程序中选择断点,把程序运行于此处时的各个变量值Print出来。

例如: System.out.print(程序的过程变量);

但是我有一个朋友自己写了一个设置断点的工具函数,也是非常好用的,共享给大家:

boolean debugflg=false;//调试标志

Debug() //设置断点

 

private void Debug ()

 { 

System.out.print(程序的过程变量);//打印程序的当前变量的值

      while(debugflg){}                  //等待用户消息

 }

 public void keyPressed(int keyCode)

 {  

  debugflg =false;

 }

 

校屏

大家是否都有过这样的经验:在一个设备上作好的程序当拿到另外的设备上跑的时候,      即使程序中的API都是通用的,还是会出现这样那样的问题。其中最令人头疼的可能就是图片和文字都会因为设备的屏幕大小不同而乱掉。乖乖,又是好一番调整。J 如果想让自己写的程序能够畅通无阻的运行在各种平台上,第一是要考虑用通用的开发包,第二当然就是需要校屏,也就是将自己要显示的图片,文字用程序动态的确定位置,使之在各种大小的屏幕上都能达到居中等效果。这样才能保证程序的通用性。

实例如下:

public class MyCanvas extends Canvas

{

 private  final int addX;     //坐标矫正

 private  final int addY;

 private  final int screen_X;  //屏幕顶点

 private  final int screen_Y;

 private  final int str_X;     //字符串顶点

 private  final int str_Y;

 private  final int pic_X;    //图形的顶点

 private  final int pic_Y;

 

 public MyCanvas()

 {

  //取得当前手机屏幕的高度和宽度

 int  height = getHeight();

 int  width = getWidth();

 

  //坐标矫正量 

  addX = (width-120)/2;

  addY = (height-142)/2;

 

  //初始化屏幕参数

  screen _X = addX + 48;  //屏幕顶点

  screen _Y = addY + 10;

  str _X = addX + 19;     //打印字符串的顶点

  str _Y = addY + 103;

  pic _X = addX + 36;    //显示图像的顶点

  pic _Y = addY + 34;

  }

}

 

我记得一位老鸟曾经告诉过我:程序往往用90%的时间去运行10%的代码。因此,与其努力提高所有代码的效率,不如找出代码中的“瓶颈”,使之更高效地工作,这样会得到更高的收益。 呵呵,有时候细心的逐行审查自己的代码,往往会存在几条语句能大大的提高运行的效率。但是如果你想程序能够得到更高的效率,那么就请在写代码之前精心的设计和选用合适的算法把。



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=762913

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章