手机用了十年了,像我这样一直没换号码的老客户,移动公司也不说给点什么优惠,实在是很气愤的事。再说用了N年的Nokia 6210这年头实再也拿不出手,无奈,只好自己掏银子买新的。选择手机也费了好大周折,Nokia 7110、Dopod 585、Noto E680i之间犹豫了好久,最后选定小i。一方面性价比最划算,另一方面就是上面有仙剑奇侠传。机器拿到手,才发现这想玩这游戏,还是比较费劲的,虽然很快就在 ccmove 上找到了相关破解,但整体画面,操作都不尽人意。客观讲,不到300Kb的游戏能这样也很不错了。不过,Intel XScale CPU 312MHz 跑这样小儿科的东西未免有些浪费,所以就萌生了把原来DOS版的仙剑奇侠传原样移植到小i上去的想法。
2005-11-11 16:09:55
2005-11-11 16:34:03 准备工作开始小i内嵌Linux系统,而且MOTO没有开放开发环境或者SDK,用Linux去做显然不太现实。而且MOTO为了防止用户乱装东西,屏蔽了Linux的许多东西,只能去安装运行Jave的东西了。基于XScale的linux可以去这 http://www.linuxgazette.com/node/9786 找资料,据说编译过的程序可以在小i的linux下直接运行,但我新机器用了不到一周,不感做这些测试,还是以后在考虑。
开发环境最后选定 J2ME 。在 http://www.motocoder.com/motorola/pcsHome.jsp 下载到最新的开发包,其中包含了小i的模拟器。当然也可以直接用 Sun 的 J2ME 去做,稍微修改一下默认的模拟器也可以。偶J2ME研究没几天,也没什么J2EE的经验,一切都是从头开始,呵呵。
仙剑奇侠传源版文件要自己准备了。我找出珍藏N久的仙剑95。还行,在XP上能运行。
网上有好多人在研究仙剑资源文件的格式,推荐去 http://palxex.ys168.com/ 找资料,战长很无私。崇拜ing...
2005-11-11 17:10:26 仙剑 .MKF 文件 和 JY_1 压缩算法仙剑的资源文件都压缩在 .MKF 文件中了,格式也非常简单,拿Delphi解开很容易。但是解开后,还有部分文件是用 JY_1 算法加密过的,这个算法的解密代码在楼上 藏宝阁 中有。可惜代码是VC写的,我没时间费劲去把那些跟汇编没什么区别的代码转到Delphi下,就偷个懒,用BCB做了个DLL。下面是Delphi的用法。方便只会用Delphi的人用。
{$WARN SYMBOL_PLATFORM OFF}
function DecodeJY(src, dst: PByte; isdos: integer): integer; cdecl; external 'DecodeJY1.dll' index 1;
{$WARN SYMBOL_PLATFORM ON}
PS: dsk 这个地址要预先分好内存的,不然要出错的。至于要分多少,src中用delphi读也不难,具体偶也不罗嗦了。isdos是说明资源版本的,0 表示Windows版的,其他数就是DOS版的了,DOS版本的应该是JY_1算法,Windows版的这个算法不一样。我没找到DOS版本仙剑,只测试了一下仙剑95。此处推荐用Windows版的仙剑,毕竟windows版的资源文件(.wav,.mid)格式比较好搞。
还有个问题,就是MIDI文件。仙剑95的MIDI在 J2ME 里听的还可以,到 MOTO 里去乐器就走样了,估计以后还是个麻烦。暂时对MIDI没什么研究,以后在说吧。
今天先到这,休息....仙剑 .MKF 文件 和 JY_1 压缩算法 2005-11-14 13:00:46 仙剑中所有物品道具的图片仙剑中所有物品道具的图片放在 BALL.MKF 中了。
.MKF是子文件偏移表加子文件数据的格式存放的,具体解法就不多说了。BALL中存放了所有道具的图片,图片是以类似 RLE 方式存放的。文件头4字节应该是调色板编号(见PAT.MKF),然后两个Word分别是宽和高,之后就是图片数据库了,取一个字节,如果大于$80,说明是连续(??-$80)个透明点,再取一个字节,应该是小于$80的数,说明后面连续的(??)个字节是点的颜色(颜色来自调色板)。
读 ismyway 老兄的 java 代码时,说有 $7F 的特例,有注释“very special case!”。但再Pal95的BALL.MKF中没有发现,不清楚意义。
PAT.MKF 就是调色板了,应该是有9个,其中有两个子文件包含2组调色板,暂时不清楚意义,;临时用第一个调色板测试用。
Palette: packed array [0..255] of
packed record
r,g,b: byte
end;
RGM.MKF 格式一样,存放角色头像,就是对话时用的那个。 2005-11-14 14:04:12 战斗背景图仙剑的背景图放在 FBP.MKF 文件中了,包括战斗中的背景,属性窗背景,结局等静态背景画面。所有子文件都是压缩的,用前面的解压函数可以解出 64000 字节的文件,内容就是一个 320x200的位图,调色板使用 PAT.MKF 第一个就可以,有几个需要换调色板,具体什么时候换暂时不清楚,以后再说吧。
PS: 昨天装了个 vNes 的模拟器在小i上,看说明时发现,J2ME不允许访问.jar之外的文件,游戏的所有资源文件必须放到.jar文件内,于是他提供了一个程序,用来把要玩的游戏ROM文件压到.jar中去。也就是说,如果java板的程序写好,也必须把这些MKF文件和程序的.class文件一起做到.jar中去。.jar本身就是一个zip文件(把后缀改.zip后就可以直接用winzip打开)。所以开始考虑,有没有必要把MKF解开。去掉一些没用的资源文件,毕竟Pal95要30多兆的。不晓得小i能接受多大的.jar文件,给仙剑减肥是必须的,首先应该是声音文件。FBP中有几个图是游戏制作人员的名字,这几副图必须保留,哈哈,这可都是些偶崇拜的高人啊...
PS: 我的小i还没配内存卡,本机的50M显然不够用的,等银子ing ...
2005-11-15 9:20:06 过关动画以及以及大宇的LOGO过关动画以及以及大宇的LOGO存方在 RNG.MKF 文件中了,文件本身没有压缩,但文件中的每个子文件是按MKF方式存放的每个动画的每帧图像,每帧图像经过JY_1的算法压缩过,用前面的解压函数解开后,得到一个压缩的图像(320x200)。这个图像压缩算法也比较过分,按"命令+值+[次数]"形式顺序存放。具体算法不多说,可以参考“藏宝阁”中的代码。
PS:按理讲那时候已经有avi格式了,不过大宇没有采用,还是照搬了DOS时代的东西,用这种方法也有不小的压缩比,但如果当前帧跟前一帧图像先做下异或,然后在用上面的算法去压图像,可能会得到更大的压缩比,呵呵。看来大宇当时还是偷懒了 :)
PS:今天还遇到件郁闷的事,早上上班,发现放地下室的自行车不见了,不晓得哪位“盗衰”看上了我那白菜价的宝驴。晕倒。。。。还是我亵渎了《仙剑》这款杰作,给我的报应?! 2005-11-15 10:31:03 其他位图文件ABC.MKF 战斗状态下敌人的动态图象(压缩)
F.MKF 战斗状态下主角动态图象(压缩)
FIRE.MKF 战斗时法术施展的效果动画(压缩)
GOP.MKF 组成游戏地图的图形单元块
MGO.MKF 主角,NPC,动态物品图库(压缩)
这几个文件结构一样,都是一些小的位图,可先用前面的解压函数解压相应的文件。每个子文件都是偏移表加数据的格式存放的,偏移表是双字节类型,数值乘2就是在内部的偏移量。每个子位图以RLE形式存放,解压同 BALL.MKF 。
PS: MGO.MKF有“仙剑奇侠传”的动画字样和动画的飞鹤,加上背景画面中的山水就是游戏的启动画面咯。准备工作到这,就可以开始制作游戏的启动画面了。
2005-11-19 13:58:07 开始 J2ME 就遇到了一个头痛的问题,内存!仙剑的资源文件太大了,程序写了没多少就发现问题了“OutOfMemoryError”。检查了一下,发现 J2ME 的模拟器默认只提供程序500K内存,测试了一下小i,也只不过2M。汗了,要知道仙剑的地图贴图块尺寸是 32x15 ,最大的一个文件包含接近500块,这样一来,要把他导入内存“int[] argb”去渲染地图至少需要900K的空间。看来必须在位图格式上做文章咯。究竟如何存储这些资源文件,还的下点攻夫。暂时还不知道小i允许多大的jar文件,但把几M大的.MKF直接做到jar里,让java解出文件,然后在用算法接MKF,在接出子文件得到图像,这一大串都让手机的CPU去做也太过分了,所以首先还要在PC上做个程序把MKF分隔解压。现在考虑把,解出来的子文件放到jar中,解位图的工作还是留给java来做,毕竟仙剑的图像数据和调色板是分开的,要直接把这些文件存成位图,那上千个文件的调色板也是不小的开销。 2005-11-20 14:54:22 还是内存的问题...不只是地图文件,还有更头疼的,那就是 RNG.MKF ,这里面包含了游戏中的几个过场动画,前面说RNG结构时有点错误,仙剑的设计人员比我考虑的细致,RNG中的每个动画,第一帧是完整的320x200位图,之后的就不是全图了,数据中只有前一帧变化后的数据。即使这样,像酒剑仙教逍遥剑术的那个动画就有410帧共953KB(最大的2M多)。全部导入内存然后解压渲染在只有2M内存的小i上是根本不现实的,所以代码改成了文件流,渲染某帧时才去解,可惜测试失败,效率太低了,每秒渲染不到2帧,郁闷啊。 2005-11-21 10:55:55 资源文件的大小也是瓶颈!在J2ME的模拟器下运行好好的程序,到小i里就不运行,代码就是把RNG的文件打开来循环显示每帧图像,按理讲是没问题的。看看被显示的文件,不过900K吗!试试小点的,果然就没问题了,看了小i的 InputStream 有大小限制。这也是不可避免的,毕竟创建 InputStream 时 java的VM要从 jar 里把文件解压出来,小i可能没有按照流的形式去解zip块,而是整个解到内存去了,这样一来,超过500K的文件必须分割一下咯。
PS: vNes 的模拟器只能玩256K以下的ROM,512的ROM玩不了,看来并不是 vNes 的问题,而是小i的VM就只能读500K以下的文件(400多K的文件曾经读入过,没问题的)。 2005-11-25 13:59:49 晕,字符集!终于写到菜单部分了,本来几个中文文字是写在代码中测试的,后来把仙剑的文字资源文件S.MSG和WORD.DAT加进去后,问题出现了。在WTK的模拟器中显示好好的文字到小i下竟然全是乱码?虽然J2ME的 new String( msgTable, offset, len, "GBK"); 可以从 GBK 编码的 byte[] 转出 UTF-8 来,但是在小i中竟然报 UnsupportedEncodingException 的错误了。看了是不支持了,没折,只能先用Delphi把那两个文件转成Unicode,然后给J2ME用了。
public String getWords(int index){
StringBuffer sb = new StringBuffer();
sb.setLength(5);
index *= 10;
for(int i=0;i<5;i++){
sb.setCharAt(i, (char)((wordTable[index] & 0xff) | ((wordTable[index+1] & 0xff) << 8)) );
index+=2;
}
return sb.toString().trim();
}
仙剑的M.MSG文件200K多(仙剑的所有对话,SSS.MKF中的的4个子文件是该文件的索引),对小i的2M heap 来说太大了。因为J2ME的文件流跟DOS下不同,DOS下打开一个文件,内存中只有个几字节的FCB就够了,能够随意去读文件的任何位置,而J2ME的文件是在jar里的,随意定位读取肯定不现实。所以就把M.MSG文件按256句一个文件分开了,heap中只保留256句,这样即省了内存占用,有避免了频繁读取文件。
2005-12-4 19:37:59 这几天一直在考虑仙剑的引擎部分,并做一些基础的代码,没时间来写日记了。从藏宝阁DOWN的文档都是收集起来的一些资料,由好多人写的,虽然经过整理,但感觉还是非常的杂乱。我想再仔细整理一下,但一个人的能力还是有限,只能做到什么地方去分析一个地方了。
下面先说说RPG游戏的核心,仙剑的脚本引擎。(从 夜烟、外塞之雾、ylmson 等大侠分析的基础上做点总结)
跟仙剑的脚本相关的东西主要放在 SSS.MKF 文件中了,共5个子文件(下面用SSS#0 ~ SSS#4表示)。
SSS#0:仙剑中所有与事件相关的物体信息表,每个事件物体占32字节(以后称 EventObject)。
word[0]: 全部为“0x0000”,无任何意义
word[1]: 座标 X,
word[2]: 座标 Y, 为地图的象素座标
word[3]: 图层。即如果该坐标有2个事件,那个显示在上方。负数表示低于地面(?)
word[4]: 触发脚本。即以触发该事件时调用的脚本
word[5]: 即该事件在地图上自动调用的脚本,一般是特殊动作,比如行走(?)
word[6]: 触发状态,如果是0则该事件无法触发,并且标志物不显示。1、2等主要是在脚本调用时区别,比如指令49(?)
word[7]: 触发方式
word[8]: 事件标志物,对应 MGO.MKF 中的图像。
word[9]: 动态图像参数,比如说人物行走动作
word[10]: 静态图像参数,比如说人物面对的方向
word[11]: 特殊图像参数,意义暂时不明(?)
word[12]: 未知
word[13]: 时间参数,只有在存档和内存中才有用,所有自由怪物打过后,累计的时间(?)
word[14]: 未知
word[15]: 未知
SSS#1:仙剑的所有场景。每个场景8字节。
word[0]: 场景地图编号,图元和图快分别在map.mkf和gop.mkf中定义
word[1]: 场景进入脚本,进入该场景时自动触发的脚本
word[2]: 场景脱离脚本,在该场景使用引路蜂、土灵珠时调用的脚本
word[3]: 场景事件定义,上一场景的最后一个事件代号
PS: 开始我还四处找SSS#0中的EventObject是怎样索引并关联到场景里去的,因为在SSS#0中根本就没有说明EventObject是属于哪个场景的。也找不出什么可疑的文件来存放关联数据。所以,代码渲染场景时也就不知道,何时把EventObject贴出来。最后才发现这个文件中的word[3]用意。加载一个场景时,根据场景编号找到相应的行,取的地图编号(word[0]),脚本指针(Word[1],Word[2])和第一个事件物体编号(Word[3]),这时需要取跟在后面场景的信息,其(Word[3])就是当前场景最后一个EventObject的编号了。
SSS#2: 对系统、人物、物品、仙术、怪物、中毒等的说明,每个块 14 字节(DOS版是12字节?),这个文件跟仙剑中WORD.DAT文件对应,WORD.DAT每10字节一行,就是该文件对应行的名称。(数据很多,但跟地图引擎和脚本引擎关系不是太大,暂时先不着急分析)
SSS#3: 游戏中所有对话的索引表,每句4字节(Int32),即对话在M.MSG文件中的偏移量。下一句的便宜为该句的结束偏移。
SSS#4: 游戏的核心脚本,每8字节一行,分别是 “指令、参数1、参数2、参数3”。至于每个指令的说明,我就不写了,代码中用到时,就写到代码的注释里吧。
说完这5个文件的含义,再来说说游戏是如何跑起来的。
游戏中选择“新的故事”(SSS#2的0x0007行,修改WORD.DAT的该行字符串,显示会变,看的出游戏去改多国语言是很方便的),游戏会从SSS.MKF中加载SSS#1,取第一个场景(场景编号从"1"开始,多数情况都是从"0"开始,这种从"1"开始的还是很少有的情况)。得到 (0014 0004 0000 0000) 数据,按SSS#1说明,去加载地图0x14(空地图,只有一张李逍遥的木床),脚本指针指向"0x0004",EventObject 为 (0x0000~0x0000)。然后开始从 "0x0004" 处运行游戏脚本SSS#4。可以借助 ylmson 大侠的脚本解释程序来分析脚本,内容如下:
0004: 0046 0020 0040 0000 ;设置队员块位置 32 64 0
;这里的块位置是地图的块,由于仙剑地图图元是32x15的菱形,排列起来后每行都是锯齿形状的,在MAP.MKF中的X应该等于(参数1*2+参数3),参数2为Y,参数3只有"0"和"1"两种情况,说明是否是右下那个菱形位置。(本来考虑这个座标应该是指到地图中李逍遥那张床的附近,结果发现原游戏中也没显示床,误导...)
0005: 0065 0000 00c1 0000 ;设置队员形象 0000 00c1 False
;参数1是角色编号,"0"是李逍遥,"1"是赵灵儿..。参数2是MGO.MKF中的索引号,根据这个值去加载对应的MGO子文件,实际是多个RLE格式位图。参数3好像是说明是否暂缓变更形象的,false为立即更新。因为每个MGO的子文件中包含多个位图,更换后位图会指到第一帧上去,导致重画出错误的形象,所以改处设置true后,将暂缓更新,直到有0x0015的指令(设置队员方向/帧)时才更换。
0006: 0015 0000 0000 0000 ;设置队员方向/帧 0000 0 0000
;参数1为帧。参数2为方向。参数3为角色代号。
0007: 0075 0001 0000 0000 ;组队 0001 0000 0000
;仙剑中可控制的? 2005-12-7 12:34:18 仙剑95 抓屏工具这几天做地图部分,感觉仙剑中的坐标比较乱,显示事件物时,总不能把图像贴到正确的位置上去,所以考虑抓些图来帮助分析。不过仙剑窗口是8bit 320x200的,用系统的PrintScreen键抓到的都是黑图,没法看。于是制作了一个工具来抓图。程序是仿照 Direct3D SDK 9 中D3DSpy的方法作的,开始是为了让游戏能在窗口环境下玩,但是失败了,代码存在一边N久了。主要思路是游戏运行时要去调用 DDraw.dll 中的 DirectDrawCreate 创建屏幕设备,于是就自己写一个DDraw.dll 放在游戏目录下,用来调用真正的 DDraw.dll,程序在中间起个代理作用。从而也就那到了游戏的 IDirectDraw 接口。程序启动后,创建一个热键,当得到热键事件时,从IDirectDraw接口抓取图像保存到文件。
程序是用Delphi写的,稍作修改应该能用到更多的地方。
不过抓屏部分代码是我按自己的思路写的,没去细翻 MSDN 上关于 IDirectDraw 的细节用法,可能需要用 Lock 和 Unlock 的那些东西才显的专业。总之能用就OK了。
本来想在这发的,不知道怎么不让上传文件了,需要的加我的 QQ群:15604052 吧 2005-12-11 0:40:36 再分析下仙剑脚本前面分析过仙剑的脚本,那都是在别人的分析基础上的。但是当真正用代码去实现脚本时,却不能得到完全跟游戏相同的效果。
脚本部分第一次代码尝试:把脚本考虑成单线程的,当有新的脚本时压栈,执行完毕,再退栈,每屏幕刷新一次执行一句脚本。这种思路比较简单易懂,套用上面的解释后很快就发现问题了。如第二个场景中,李大婶叫醒李逍遥后的一段对话,当李大婶打了李逍遥一锅后,即走出房间,这个动作在场景的脚本中根本没有的。真正控制这个动作的脚本放在了事件物体的自动脚本中,也就是场景脚本中
0e3f: 0049 000c 0000 0000 ;设置对象状态 000c 0
0e40: 0049 000b 0002 0000 ;设置对象状态 000b 2 // <<--- 启动事件物体的自动脚本
0e41: 0009 0008 0000 0000 ;清屏并等待 8
0e42: 0065 0000 0002 ffff ;设置队员形象 0000 0002 True
所以指令 0x0049 的参数2,0:隐藏事件物体同时停止其自动脚本,1:显示该物体,2:显示该物体同时启动其自动脚本。参数1就是事件物体的代号了,上面的0x000c是李大婶拿着锅子那图,0x000B是李大婶站立和行走的图。由于李大婶的向门外行走和场景脚本是并行的,所以上面的尝试被推翻了。
第二次尝试:场景代码仍将采用压栈处理,同时为每个状态是2个事件物体创建一个事件物体脚本列表,屏幕刷新时给每个事件物体脚本一次执行一句的机会。这样做,很快又被后面的脚本推翻了,如:
0e48: 0009 0004 0000 0000 ;清屏并等待 4
0e49: 0016 000b 0002 0000 ;设置对象动作 000b 2 0 // <<<=== 问题出在这
0e4a: 0005 0000 0000 0000 ;清屏 0 False
0e4b: 003d 0037 0000 0000 ;下部显示 0037 0
0e4c: ffff 055a 0000 0000 ;显示对话 `李大娘∶`
0e4d: ffff 055b 0000 0000 ;显示对话 `是啊..还不快过来帮忙!`
0e4e: 0009 000c 0000 0000 ;清屏并等待 12
这段代码是李大婶在走到门口时转身停住(0x0e49),说话(0x0e4c),按任意键后(0x0e4d*),继续向外走。看来,事件物体的自动脚本是在 0x0e48和0x0e4e两句中或的执行的时间,而中间部分是场景代码一次执行的,而事件物体脚本没有获得执行的机会。为了证明这点,到客栈外,找在跳绳的三个小朋友对话,对话过程中,跳绳的动画是静止的。所以,两次屏幕重画之间的场景脚本执行是多句的,只有遇到类似 0009 那样的指令时,才给事件物体脚本执行的时间。而且这些翻译成“清屏”有些不妥,翻译成“RefreshScreen”可能会更好些。再就是0x0005这个指令最后一个Boolean型参数也是为这用的,false 时屏幕重画,但是并不执行事件物体脚本。
开始准备第三版脚本执行代码了,可惜今天已晚了,休息,明天再写..
2005-12-15 15:26:39 细说仙剑的地图仙剑的地图是由 MAP.MKF 和 GOP.MKF 两个文件配合使用实现的。每个文件各包含 226 个子文件。每个MAP子文件65536字节,是一个128x128方阵,每4字节描述一个块。GOP中相应的子文件是该地图块的贴图图元(32x15 的菱形 RLE 位图)。根据MAP将图元横向波浪型排列,最后得到2048x2048的完整地图。MAP中每块4字节描述如下:
1 . 0000 0000 // 0层图元索引号
2 . 0000 0000 //
|| ||||
|| |||+-- : 层标志(??)
|| +++--- : 层高
|+------- : 0层图元索引号扩展,该位为"1"说明索引号大与255(最多512个图元!)
+-------- : 是否可以移动的区域,"1"为不可进入
3 . 0000 0000 // 1层图元索引号,编号从1开始,0表示该块无1层信息
4 . 0000 0000 //
| ||||
| |||+-- : 层标志(??)
| +++--- : 层高
+------- : 1层图元索引号扩展,该位为"1"说明索引号大与255(最多512个图元!)
可以看出地图是由两层组成的,0层是地图的主体,1层是一些特殊的遮挡体,比如桌椅、树木等,但是仅仅这两层还是不能完全描述出遮挡的细节信息。所以这里出现了一个层高的概念,也就是这个块的高度(Z值)。通过这个值来判断什么时候去遮挡地图中的角色、怪物和事件物体。
如果要渲染一个完整的场景,首先要先画出地图的0层和1层,在地图上画 角色,然后画遮挡这个角色0层和1层。当多个角色怪物都在一起时,还要处理这些角色直接的遮挡关系(这部分还没考虑好)总之比较复杂。 2005-12-15 15:33:43 角色在李逍遥房间那些书橱间走到,正确实现遮挡关系的代码PalPosition为仙剑坐标系的基础类,角色、怪物、事件物体和地图都从这集成出来。
这个函数是地图类中给角色画遮挡块的。
[code]
public void maskContain(Graphics g, PalPosition p){
int offset, xx, yy, mi, lhc, offset_n;
offset = ((p.y << 7) + (p.x << 1) + p.half) << 2;
xx = 20 + 96 + ((y << 1) + half - (p.y << 1) - p.half) * 8;
yy = 160 - 16;
lhc = 0;
while ( lhc < 4 ) {
// current stand block
if ((( mapData[offset+1] & 0x01 ) != 0) && (((mapData[offset+1] & 0x0F) >> 1) > lhc)) {
mi = mapData[offset] & 0xFF;
if (( mapData[offset+1] & 0x10 ) != 0) mi += 256;
drawGop(g, xx, yy, mi);
}
if ((((mapData[offset+3] & 0x0F) >> 1) + (mapData[offset+3] & 0x01)) > lhc) {
mi = mapData[offset+2] & 0xFF;
if (( mapData[offset+3] & 0x10 ) != 0) mi += 256;
if (mi > 0) drawGop(g, xx, yy, mi-1);
}
// right-bottom block
if (p.half == 0) offset_n = 4;
else offset_n = 516;
if ((( mapData[offset+1+offset_n] & 0x01 ) != 0) && (((mapData[offset+1+offset_n] & 0x0F) >> 1) >= lhc)) {
mi = mapData[offset+offset_n] & 0xFF;
if (( mapData[offset+1+offset_n] & 0x10 ) != 0) mi += 256;
drawGop(g, xx + 8, yy - 16, mi);
}
if ((((mapData[offset+3+offset_n] & 0x0F) >> 1) + (mapData[offset+3+offset_n] & 0x01)) > lhc) {
mi = mapData[offset+2+offset_n] & 0xFF;
if (( mapData[offset+3+offset_n] & 0x10 ) != 0) mi += 256;
if (mi > 0) drawGop(g, xx + 8, yy - 16, mi-1);
}
// left-bottom block
if (p.half == 0) offset_n = -4;
else offset_n = 508;
if ((( mapData[offset+1+offset_n] & 0x01 ) != 0) && (((mapData[offset+1+offset_n] & 0x0F) >> 1) >= lhc)) {
mi = mapData[offset+offset_n] & 0xFF;
if (( mapData[offset+1+offset_n] & 0x10 ) != 0) mi += 256;
drawGop(g, xx + 8, yy + 16, mi);
}
if ((((mapData[offset+3+offset_n] & 0x0F) >> 1) + (mapData[offset+3+offset_n] & 0x01)) > lhc) {
mi = mapData[offset+2+offset_n] & 0xFF;
if (( mapData[offset+3+offset_n] & 0x10 ) != 0) mi += 256;
if (mi > 0) drawGop(g, xx + 8, yy + 16, mi-1);
}
offset -= 512;
xx -= 16;
lhc++;
if (offset < 0) break;
}
}
[/code] 2005-12-27 12:36:15 几天没写笔记了,今天再补充点刚自己回顾了一下前面的贴子,发现写问题,就不去改原文了(历史保留),在这统一整理一下。
1楼:当时以为MOTO的J2ME SDK会好些,所以说去MOTO下载SDK的,但是实际应用中发现MOTO的SDK提供的扩展功能根本没什么作用,比如让背景灯常亮的Lighting类。而且模拟器也比较烂,最后还是去 http://java.sun.com/j2me 下载的 WTK 2.2 。
2楼:MIDI文件有高人已经处理过了,可是直接拿来用,效果不错。http://swder.ys168.com/ (丢丢的宇之音)
3楼:BALL文件的每个子文件的前4字节不是版本号,也不是调色版编号,是用来说明文件中包含RLE文件的偏移量的。调色板文件多数是一个调色版的,有几个包含两个调色板,这两个调色板分别是白天和晚上用的。更换调色板是由游戏的脚本实现的。
4楼:MOTO对jar文件的大小限制比较宽,只要有存储空间够应该就没什么问题了。
6楼:MOTO的JAVA提供 2M 的 HEAP 空间。976KB RMS,RMS每条记录限制100K。(RMS存进度和设置用)
8楼:MOTO本身只有UTF-8字符集。我现在用的15x16点阵字库(来自UCDOS),跟字符集无关了。
用了一个多月J2ME,对JAVA有些了解了,同时也对Java有了新的认识。Java是一杰作,.NET也有不错的前景。“语言什么都不是”。有时间去读下李维先生的《Borland 传奇》,客观的去理解任何一款语言和开发工具吧。 2005-12-31 10:58:34 脚本引擎(续)..脚本引擎又写不下去了,起初我是把脚本分为主线脚本和事件物体的自动脚本两类分开来处理的,事件物体脚本放在循环中,主线脚本等待时给事件脚本一次执行机会。主线脚本使用堆栈处理,遇到 切换场景指令(0x0059) 时,当前脚本压栈,去执行新场景的进入脚本。但是今天发现个问题,见如下脚本:
$0B58 0050 0000 0000 0000 淡出
$0B59 0059 0002 0000 0000 转到场景 0002
$0B5A 006D 0002 0B68 0000 设置场景进入脚本 0002 0B68 // <--- 问题!
$0B5B 0049 FFFF 0000 0000 设置对象状态 FFFF 0
$0B5C 0000 0000 0000 0000 结束 IDLE
如果遇到 切换场景 就压栈的话,这时就去加载 0002 场景的进入脚本了。但是后面的指令是修改这个场景的进入脚本的。。。。
所以,之前的压栈方式处理脚本有问题。
也许是我把DOS时代的这个游戏考虑的复杂化了。 2006-2-14 14:12:13 过了个年,这程序没怎么动。花了点功夫研究手机去了。费了好大劲,终于成功 telnet 上手机的 linux 系统了。也许是为了安全,MOTO把这些东西屏蔽掉了,只允许用户去装 J2ME 的程序,而另外一类就是手机内部的软件了,最后确定是 Qtopia 应用程序。相关资料在 www.qtopia.net 上。这是利用 linux 下的 gcc 基于 Qt 类库跨平台编译出的 linux 应用程序。我对 Qt 不了解,只临时搭了个环境做了下测试。
ZTE 大唐也都开始用 Qtopia 了,也许 Qtopia 会有不错的前景。 2006-3-10 22:34:32 好久没写了,再补充点。终于在windows+cygwin下搭好了,编译e680i程序用的交叉编译器。上贴还认为是qtopia的,这回更正,应该是在 Qt/Embedded 2.3.6 基础上扩充的了的 EZX 程序,MOTO并没有公开EZX的SDK。所以做EZX还是有些麻烦的。因为有Qt/Embedded 2.3.6的基本库,直接写Qt/E的程序也可以用,只是不能套用手机的界面的主题。
|