经典收藏:J2ME Game的开发笔记

jiuzheyangaile

jiuzheyangaile

2016-02-19 13:36

最近很多朋友喜欢上设计,但是大家却不知道如何去做,别担心有图老师给你解答,史上最全最棒的详细解说让你一看就懂。
J2ME Game开发笔记-尝试IO优化
  正在开发的一个游戏,由于读地图的时候做了图片切割,所以速度比较慢。(在我开发上一个游戏的时候,读取地图时没有装载切割图片,速度非常快,看来IO操作的速度和createImage,drawImage相比是微不足道的)对于IO的优化也许根本不会明显的提高速度,但我还是试了一下。
  
  分析了一下代码,在最初的代码中为了比较方便的读取各种类型的数据,使用DataInputStream套接InputStream。可是我仔细看了一下我读取得数据,居然都是byte,唯一的一个char也是被我用两个byte手工组装起来的。这下,DataInputStream看来是不需要了。于是我做了个实验,没改动之前读取地图耗时1242ms,将DataInputStream去掉直接使用InputStream耗时1065ms,虽然每次试验的结果都稍有不同,但大概还是节约了200ms左右。
  
  还能再加快点吗?再观察一下代码,我发现数据是通过多次的read操作读取进来的。太过频繁的io操作会不会降低速度呢?假如用一个字节数组作缓冲一次性将数据都读进来会不会快点?嗯,试一试才知道。但是我怎么知道一个流的大小呢?InputStream的avaliable方法总是返回-1啊!打开两次流,第一次先计算大小?对了,还有一个方法。直接将文件大小写到文件前面。地图文件是用自己的编辑器生成的,知道大小很轻易。于是我在文件前面用两个byte纪录了文件的大小,先从流中读取2个byte,得到文件大小后,再用read(byte[],int,int)方法将整个流读取到缓冲中。然后,我的所有数据操作都从缓冲中读取。好,试验一下,结果是:1154ms。阿? 慢了近100ms。事实证实了这个猜想是错误的。原因?也许只有了解KVM的机制才知道。
  
  弄完速度的问题,我又觉得读取文件的try块太大了,因为是边读边处理数据,所以try块变得很大。try块太大会增加class文件的大小。于是我用一个方法将读取byte的操作封装起来,当然这个方法是声明为private static的,但究竟能不能内联,只有编译器和kvm才知道。在这个方法内部从流中读取一个字节的时候采用了try,catch结构,这就使一个大try块分散成若干小try块。试验了一下,耗时1089ms,诶,还是慢了点。现在对于速度的要求比空间更高,更何况减小try块节省的10几个字节打包后基本忽略不计了。所以这个优化又失败了。
  
  小结:能使用简单流的时候就不要使用复杂流,不要太相信理论上的说法,只有试了才知道。
  
  注:试验数据是Nokia3100手机的实机测试数据,在Nokia 3300上这个数据更小些,最快约800多ms
  
  压缩还是不压缩
  做J2ME的都知道Midlet Suite的容量实在太小了,于是不免想做点压缩。前些天,我就尝试了一次压缩。我自己定义的地图文件里有3层数据,其中2,3层有大片连续分布的相同的值。 唉?我一琢磨,使用一个简单的行长编码压缩,仅对这个值进行行长编码,算法很简单速度又不慢,却可以大大减小地图文件的大小。看起来真的很不错诶!说干就干,忙了半天,又改地图编辑器,又改游戏中读地图的代码。总算搞定,试了一下,原来2.23k的一个文件被压缩到900多字节。似乎很不错啊,接着我打了个jar包,却忽然发现这个jar文件似乎并没有比原来小阿!似乎还大了点。我连忙找出备份的代码,果然原来的jar更小点!怎么回事啊??我忽然想到,jar本身就是压缩格式的。难道。。。我赶紧用WinRAR打开两次的jar文件观察。~~~~~原来如此!原来的jar中,2.23k的文件的包大小为185字节,而我现在的jar中,900多字节的文件的包大小为216字节。也就是说,我自己先压缩一遍的文件打包后还不如不压缩的小!
  
  看来自己做压缩之前,一定要先看看你想压缩的文件在包里面的大小。还有对于png文件,使用某些工具优化后,在包里面的大小却变大了。这个还真是要注重阿~!
  
  移植一法
  近日观察某些游戏的源代码(反编译后的),发现有个方法挺方便游戏的移植的。定义一个接口(比如stringTable)将游戏中所用到的静态字符串都定义为接口的常量。然后,让使用到这些字符串的类实现stringTable接口。这样移植的时候只要修改接口里面的字符串就行了。当然,对于游戏中坐标的定位,最好使用getWidth(),getHeight()还有Font类的方法stringWidth,不要定死了。这样的话,移植工作就比较轻松了。
  
  键盘响应
  不同的机型对于键盘事件的响应不一样。经过我的测试,Nokia 7210,3100一次只能接受一个按键信息。(我写了个测试程序,发现假如一个键被按下后没有松开,则KeyPressed事件不会再产生,即其他键的按下操作无效)所以,用缓冲处理控制精灵运动时,假如规定只能四方向运动。假如up已按下,再按下left,精灵的运动方向并不会改变。不过将按键缓冲。按下up,按下left不释放,松开up---精灵就会向左运动。(在松开up后产生了left的KeyPressed事件!希奇吗?松开up后我并没有进行"按下"left这个动作--left键在up松开前就被按下了且没有松开。似乎机器一直在监测键盘上各键的状态,并且有一个等待队列。)
  
  在wtk的标准模拟器上就不同了。它可以接受多个按键“同时”按下的事件。所以假如用四个并列的if处理,精灵是可以斜着运动的。假如用if else处理,则假如已经按下一个方向键,然后再按下另一个,是否能改变方向受到if else 语句中顺序的影响。即,假如是 if(up) else if(left),则会先检查up键,所以假如已经按下了left,再按up是可以向上运动的,反过来就不行了。(这个自然:)
  
  其它的机型由于手头没有机器,我也没试过。应该也是如此吧。
  
  多机型移植经验谈
  开发的时候平台是Nokia 40,然后移植到Nokia 60, Moto V, SE等,总结一下大概需要几个版本。
  1 Nokia 40版, 使用Midp1.0+Nokia UI API
  2 Nokia 60版, 使用Midp1.0+NOkia UI API
  3 Nokia Midp2.0版,如6600,7610,使用Midp2.0
  4 Moto V版,使用Midp2.0
  5 SE版,使用Midp2.0
  6 三星s100,s200,c100,使用Midp2.0
  
  几点开发经验:
  1 各机型之间最大的差别就是屏幕大小不同。所以游戏中要能自适应屏幕大小
  2 不使用Midp2.0的GameAPI会比较方便移植,只要自己封装切图,旋转等函数即可。NokiaUI API和Midp2。0都支持图片选转。2.0支持的更好。注重Nokia 60不支持创建可变的透明图片,所以要用其他方法代替。
  3 NOkia 6600,7610的UI API有问题(图片旋转),所以用了Midp2.0代替
  4 支持MIDP2。0的机器程序大致相同,其中MOto,SE,SX都差不多。但也有细微差别。如SE不支持全屏。所以screenSizeChanged方法无效。
  5 说说声音播放。NOkia s40上我果断不用声音,一是容量限制,二是太难听。其他机型都可以支持midi和wav.不过没有发现可以同时播放2个midi的机型,moto v和se都可以同时播放midi和wav,nokia则不行。
展开更多 50%)
分享

猜你喜欢

经典收藏:J2ME Game的开发笔记

编程语言 网络编程
经典收藏:J2ME Game的开发笔记

J2ME开发入门专题系列之一:J2ME概述

编程语言 网络编程
J2ME开发入门专题系列之一:J2ME概述

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

J2ME游戏开发实例讲解

编程语言 网络编程
J2ME游戏开发实例讲解

J2ME学习笔记(4)—用MIDP API开发MIDlets

编程语言 网络编程
J2ME学习笔记(4)—用MIDP API开发MIDlets

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

J2ME蓝牙程序开发实战入门

编程语言 网络编程
J2ME蓝牙程序开发实战入门

如何使用“月蚀”进行J2ME开发

编程语言 网络编程
如何使用“月蚀”进行J2ME开发

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

iphone的qq2018怎么降级

iphone的qq2018怎么降级

J2ME MIDP 提供的最重要的图形元素

J2ME MIDP 提供的最重要的图形元素
下拉加载更多内容 ↓