基于j2mejavaplatmicroedition手机rpg游戏研究_第1页
基于j2mejavaplatmicroedition手机rpg游戏研究_第2页
基于j2mejavaplatmicroedition手机rpg游戏研究_第3页
基于j2mejavaplatmicroedition手机rpg游戏研究_第4页
基于j2mejavaplatmicroedition手机rpg游戏研究_第5页
已阅读5页,还剩46页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、目 录项目小组成员2摘 要2关键词2一、游戏简介以及世界观4二、运行环境及开发环境41、运行环境42、开发环境53、开发思路5三、部分开发工具介绍51、Eclipse52、Mapwin5四、可行性分析51、商业层面52、技术层面6五、概要设计61、游戏设定与相关规则62、游戏代码设计6六、详细设计121、开发准备122、个类的功能133、网络版14七、编码实现151、Tales类以及生命周期的实现152、FCanvas类、地图切换,坐标转化以及界面要素的实现153、HeroSprite类以及键盘事件,进度更新的实现194、MonsterSprite类以及人工智能的实现225、网络版服务器端23

2、6、网络版客户端24八、使用指南25九、后记27基于J2ME的手机RPG游戏研究-征途开发记项目小组成员专业年级: 软 件 02 级参与项目者: 莫紫东(主程序员) 周琳娟 (美工) 文鹏(网络程序员) 崔永志(游戏策划)摘 要本游戏是基于J2ME平台(MIDP2.0,CLDC1.0)开发的手机游戏,目前在DOPOD515以及MOTOROLA V500机型上调试通过,其他对应版本因为没有调试环境,暂时没有开发。主要是实现单机情况下的仿暗黑破坏神的ARPG类游戏,联网版实现类似传奇MMORPG游戏框架,游戏特效使用AE,PHOTOSHOP,FLASH制作,服务器使用J2EE Servlets实现

3、。关键词J2ME,J2EE,MIDP2.0,CLDC1.0,Eclipse,Eclipse me,JDK,WTK,AE,PHOTOSHOP,智能手机,JApps,FALSH,ARPG,MMORPG,手机游戏,在线版手机游戏,精灵,碰撞检测,AI,区块地图,滚屏,层,等级,经验值,HP槽,持久存储,PNG压缩,层叠关系,物品掉落与拾取,金钱掉落与拾取,装备,键盘事件,低级绘图,装载进度条,界面开发,地图切换,地图拼凑,主角/英雄,面向对象,网络编程,游戏逻辑SUMMARYThis game is a mobile game based on J2me Platform,have tested s

4、uccessfully on spv515 and motorola v500,and others is not yet.Our purpose is to implement a ARPG just like”diablo”.And Online Edtion is wanted for a MMORPG just like”MIR”.Game effects were made by Adobe After Effect,Adobe Photoshop and Macromedia Flash.Game Server was made by J2ee Servlets.KEY WORDS

5、J2ME,J2EE,MIDP2.0,CLDC1.0,Eclipse,Eclipse me,JDK,WTK,AE,PHOTOSHOP,Japps,Flash,ARPG,MMORPG,Mobile Game,Online Mobile Game,Sprite, Collision Test,AI,Tiled Map,Scroll-Screen,Layer,Level, Experience,Hp,Record Store,PNG Condensation, Cascade Relation,Item Drop & Get,Gold Drop & Get,Gears,Key-boar

6、d Event,Low-level Graphics,Load Bar,Interface Development,Map Change,Map Tiled,Hero,OOP, Net Programming,Game Logic要約携帯電話j2me(midp2.0、cldc1.0)開発。今SPV515MOTOROLAV500成功、他対応環境、。僕主目的DiabloARPG作。、mirMMORPG。効果AE、PHOTOSHOP、FLASH、J2EESevelets開発。J2ME,J2EE,MIDP2.0,CLDC1.0,Eclipse,Eclipse me,JDK,WTK,AE,PHOTOSH

7、OP,知能携帯電話,JApps,FALSH,ARPG,MMORPG,携帯電話,ONLINE携帯電話,(Sprite),触,AI,地図,層,階段(),経験値,HP,PNG圧縮,重関係,落手入,金落手入,装備,事件,開発,地図切替,地図組立,主役,面向对象,論理一、游戏简介以及世界观1.1创意 本游戏的创意来源于著名的游戏暗黑破坏神和现在流行的MMORPG游戏。暗黑破坏神是一款经典的ARPG游戏,奠定了现在ARPG游戏的基础。2001年暗黑破坏神2的资料片毁灭之王发售,让游戏界有进入了一个新的时代网络游戏时代。因此我以他为基础想在手机上实现一个无线的联网ARPG游戏。1.1游戏背景 这是一个桫坨罗

8、国。人民过着富足祥合的生活。兽族和人组和直到有一天一匹跛狼缓缓的从荒原"走来,拖着带血的残腿,恐惧的眼神让它看起来毫无以往的凶猛威风"数天后,野蛮的兽人和身体变了形的各种野兽,举着带血淋的武器,携着疯狂的.嘶喉着杀了过来. 所过之处,哀鸿遍野、了无人烟沙海的尽头究竟发生了什么事,使的万物如此的疯狂,和平的额人们充满了恐惧和疑问。终于消息传来,在末日火山居住的暗魔族的魔王魔罗终于在火山中复活,他挈带着愤怒,怨恨来报复人族了,他的暗魔血气是首族暴筐,野兽变种。魔罗的力量控制着他们杀来了.在这灭顶之灾来临之际,人族的杰出者-英雄终于拿起了手中的武器,用爱智慧和信念来阻挡暗魔的肆虐

9、,带者爱他的人和他爱的人的期望,踏上征途。1.2 游戏文化 魔幻架空世界观,以西方中世纪的文化为背景。共有三种族:人族,兽族,暗黑魔族。人族的刚猛的剑士,高贵的白袍的法师,阴暗神秘的术士。还有野蛮的半兽人,兽人,强兽人;暗魔一族;当然还有各种洪荒猛兽。英雄有其信仰,剑士以他的荣誉为第一。法师身份高贵,术士崇尚利用一切为作战力量。1.3 产品定位目前,手机游戏产业在中国已正处于高速发展阶段,其消费者对游戏需求与游戏选择上已有更多更全面的认识。该游戏上手难度适中。带有普通网游的特点,同时具有无线连网能力,方便你随时随地的娱乐。主要以有一定网游经验的消费者和有手机游戏消费这为对象。在年龄上主要以17

10、28岁玩家为主要目标群体。二、运行环境及开发环境1、运行环境目前测试成功的环境为多普达515+JAPPS(Smartphone上的JVM)以及摩托罗拉V500,如果机器支持MIDP2.0理论上能方便地移植2、开发环境客户端:Windows Xp Sp2 + J2SDK1.4.2.07 + WTK2.2 + Eclipse3.0.2WIN32 + Eclipseme0.90+Adobe After Effect6.0+Adobe Photoshop CS+Macromedia Flash MX2004+Macromedia Fireworks + Mapwin1.4.11 + zlib.dll1

11、.1.3.0 + libpng12.dll 1.2.5.14743、开发思路主要利用配置好的Eclipse进行J2ME平台的代码开发,关于美工方面,在模拟GBA游戏王国之心以及游戏秦殇2复活里切取角色图样,导入PS中处理,去掉背景,利用FLASH调整图片位置,导出PNG格式供J2ME使用,期间使用AE处理部分特效,地图编辑器Mapwin编辑地图,代码编写完成经调试后,利用WTK发布工具发布为可供手机使用的JAR以及JAD文件。三、部分开发工具介绍1、Eclipse(JAVA 集成开发工具,具体略)2、Mapwin(地图编辑器,具体略)四、可行性分析1、商业层面当今的国内游戏市场一股开发手机游戏

12、的热流正在兴起,不少市场分析家都称手机游戏是继网络游戏之后游戏市场的又一热点,目前国内的手机游戏市场也日趋成熟,收费模式日趋合理,对于在游戏业有报复的同学们,正是一个进入的好时机,我们也正是看到了这样的机会,才着手做这样一部游戏。目前的手机游戏有两个大的发展趋势,一是3D化,毫无疑问,玩家们都希望看到更好的游戏画面,但一方面碍于手机机能有限,另一方面由于我们工作室成员在3D图形方向的沉淀的原因,暂时也没有能力去做;而另一个方向则是网络化,喜欢玩网络游戏的玩家们都希望有朝一日能随处都能升级,都能玩着自己钟爱的网络游戏,如果能将现在的网络游戏手机化,让PC平台以及手机平台的玩家们都能在一个世界中冒

13、险,给玩家们带来的诱惑无疑是巨大的,虽然碍于现在手机无线上网的带宽及费用,目前还不太现实,但一旦手机进入3G时代,这绝对是创造中国另外一批首富们的市场,所以这次我们的游戏就定在了这个方向,虽然暂时不太有可能,但我们先行解决这方面开发的上层技术问题(目前利用红外进行调试),一旦突破3G的技术瓶颈,就能抢到先机。2、技术层面从暑假开始,我们工作室的成员开始了J2ME的学习,经过了一个暑假的沉淀,加上大二时候NIIT课程开设过JAVA基础课程,所以对JAVA本来有一定程度的了解,而这次的项目虽然具有不少挑战,但我们一定能克服,而且经过这次的项目,相信我们的JAVA编程能力一定能上一个台阶,对面向对象

14、思想的认识也会再上一个台阶。五、概要设计1、游戏设定与相关规则游戏操作 操作界面模仿暗黑,并参靠考GBA游戏王国之心来设定。采用二唯画面第三人称视角。另外ACT的操作采用一键决定,这样利于手机的操作。游戏特点 每个人都有自己的生活方式,可以活得潇洒,但要活的辉煌,英勇的剑士,敏捷的猎人,神秘的法师。大家走在了一起,共同背负起了命运的责任。为了爱自己的和自己爱的人,为了美丽的土地和温暖的家园而踏上了征程。用自己的信念和智慧以及爱去阻挡怪物前进的脚步。该游戏具备了丰富的系统功能,包括PK、聊天、交易、战盟、组队等等系列,而且每个功能都有丰富选项,全面满足玩家需要。尽可能的实现PC平台上的网络有游戏

15、所具有的功能。 技术特点,在手机上无线联网运行,方便玩家随时随地的去实现自己的英雄梦。游戏类型 原定 MMORPG 现阶段开发 单机 ARPG。玩家在游戏中要操作什么 玩家要操作一名角色在这个世界里不断的成长,从一个平民一步一步走上英雄之路。在不断的战斗中提高自己的各项属性和能力。交互功能 1)与NPC的交流 2)与玩家交互 聊天2、游戏代码设计既然是用JAVA进行开发,面向对象是必然,主角和敌人和地图都写成类,还有控制这些内容的类,如果要生成新的敌人,传相应参数进行实例化,就能自动生成,首先应该定义出游戏的流程,流程图如下:是否选择联网版以及是否退出选择单机根据选择读取记录选择进度单机初始化

16、游戏,实例化显示标题画面选择网络连网初始化,实例化结束开 始选择退出是根据记录加载英雄数据是否回到主画面是主角是否生存否死亡处理,同时回到诞生地否开始作图,处理逻辑类的结构:Tales:继承了MIDlet类,进行MIDlet的生命周期的控制SFCanvas:继承了GameCanvas类,进行游戏画面的描绘和操作ASprite:继承了Sprite类,为了实现英雄类和怪物类的公有属性HeroSprite:代表英雄的类,继承自ASprite类MapTiled:代表地图的类,继承自TiledLayer类MonsterSprite:代表怪物的类,同样继承自ASprite类下面是单机版的类图:MIDlet

17、GameCanvasDefault PackageTalesSFCanvas<<Interface>>Runnable<<Interface>>CommandListenerASpriteHeroSpriteMonsterSpriteMapTiledSpriteTiledLayer1*1*1*NPCSprite1*由于类比较多,因此继承聚合关系也显得有点复杂。聚合于SFCanvas类中的各对象,除了HeroSprite之外都可以有一个或者多个。继承自MIDlet类的Tales类只负责了MIDlet的生命周期控制,而画面上的描绘以及部分界面操作则是

18、交给SFCanvas类来进行,研究过J2ME的在这里可能会感到奇怪,为什么MIDP2.0中专门提供了Sprite类,我却还要设立一个ASprite类,这实际上是为了实现一个效果,因为在画面绘制过程中需要对比包括主角怪物在类所有精灵类的Y坐标值,然后决定重叠关系,所以需要一个能统一这个值的类,而且这个属性本来就是精灵类都公有的属性,虽然会增加一些额外的资源消耗,但权衡利弊,还是决定新建一个类,关于这点在详细设计中有讲解。这里我想顺便为初次接触MIDP2.0的朋友们解释一下MIDP2.0中新增加的几个类,不然可能会很困惑。GameCanvas:继承自MIDP1.0上就有了的Canvas类,在新增几

19、个键盘值基础上,增加了几个很方便开发的方法,包括flushGraphics()(直接对目前的Graphics类进行双缓冲,以前用MIDP1.0开发的时候,想必很多初学者都对双缓冲困苦不已),getKeyStates()(可以直接捕获几个编写游戏时常用的按键返回值),paint(Graphics g)(主要用来描绘另外几个MIDP2.0中新增加的类)Sprite:包含在MIDP2.0中新增的game包中,有了这个包真的是方便了很多游戏开发上的工作,比如这个精灵类,如果是在之前的MIDP1.0中,开发者们还需要自行切割图象,自行形成图象序列帧,现在就不需要了,在该类的其中一个构造方法中,可以直接指

20、定单帧图片大小,然后生成的类就自动切好了图片,并且序列也排好了,只需要在程序中合适地使用方法setFrameSequence(int)就行了。另外该类中一个非常重要的方法collidesWith(Sprite s, boolean pixelLevel)也非常管用,这样检测两个精灵的碰撞就变得非常简单了,同时该方法还支持与地图的碰撞检测,这样如果地图中如果有不能跨过的地方(比如湖海,山崖等)就可以将这些放到另外一个图层上,但这次我们在项目中没有这么判定,一方面有素材采集上的原因,另一方面也考虑到碰撞回增加资源开销。TiledLayer:同样包含在MIDP2.0新增加的GAME包中,该

21、类的主要是方便区块游戏的开发(一个很典型的例子就是ARPG游戏的背景,当然实际上目前大多数的2D游戏都是基于区块的游戏开发,区块游戏开发有很多好处,这里就不详述了),在其构造方法的时候,也直接就讲传入的图片按参数切割成区块了,其提供的几个主要方法比如setCell(int col,int row,int tiledIndex)就可以方便地将区块填充到地图上,另外还有专门制作动态区块的方法,在这里就不详细叙述了。(详情请参阅J2ME API速查手册)(1)、下面是网络版的类图:服务器端<<Interface>>Socket<<Interface>>

22、ServerSocketThreadServerClientServerPackage(2)、网络客户端Default PackageGameClientASpriteHeroSpriteMonsterSpriteMapTiledSpriteTiledLayer1*1*1*NPCSprite1*<<Interface>>SocketOtherHeroSprite1*SFCanvasGameCanvas<<Interface>>Runnable<<Interface>>CommandListenerMIDlet(3)、数据库

23、本网络版的数据库采用的是Oracle9i,目的是为了跨平台的使用。服务器端类说明:Server:创建了一个服务器器套接字,实现了端口号13(不必为其分配IP,因为它已经在它代表的那台计算机上),它在一直循环等待客户的连接,建好一个连接以后,accept()就会返回一个Socket对象,它是那个连接的代表,将此Socket存储在数组中,方便以后信息的发送。Client:为了能够服务于多个玩家,因此Server必须是多线程的,当每一个玩家登陆上来以后,建立好连接后,就实例话一个Client,它将保存该客户的Socket信息,并且将处理该客户的各种请求。网络版客户端说明: 网络版的客户端和单机版的客

24、户端最大的不同是,要先登陆成功才能实例化SFCanvas,并且多了一个OtherHerpSprite类,由它来处理其它玩家的信息。GameClient:它实现了一个SocketConnetion的接口,由它来连接上服务器。登陆成功以后,它一直监听来自服务器端的信息OtherHeroSprite:和monster类有点类似,它专门用来处理其它完家的状态包括实例化其它完家,更新该完家的坐标数据库设计说明:由于现在网络版的开发处于研发状态,所以开发的进度很慢,所以现在数据库里也只有玩家的基本信息一张表,里面包括玩家的ID,用户名,密码,和现在的状态(在线,离线)六、详细设计1、开发准备开发的准备上,

25、首先应该确定游戏中所用到的源图片,由于J2ME仅支持PNG格式图片,所以应将切取下来的图片保存为PNG格式,考虑到手机游戏的容量限制,应该尽可能的减小文件体积,这里我们使用PHOTOSHOP进行切图,保存为一般PNG,再放入FIREWORKS中保存为压缩格式,当然PHOTOSHOP也能保存为WEB所用格式,不过保存后的效果不如FIREWORKS来得满意,一般来说都能将体积压缩到PS保存的1/51/10,而且基本感觉不出太大的差别。图象的名称来说,主要有代表主角的mainch.png,代表沙漠地图的title.png,代表敌人的monster.png以及一些其他用于绘制界面的图片,这些图片都存放

26、入项目中的/res目录下,部分图片如下:mainch.pngtitle.png2、各个类的功能Tales:实现MIDlet的生命周期,其中有些比较重要的功能,比如在手机电话来的时候的处理情况,单机版应该能暂停游戏执行,网络版应该能立即退出游戏SFCanvas:这个类是实现整个游戏的容器,Sprite,Map都应该在这个类中实例化,以及控制线程的执行情况,”Canvas”即是“画布”,关于图象处理的事情都应该包括在这个类中,比如界面等,都划进这个类。方便的是J2ME提供了这样一个类,大家写程序的时候都有了个规范。另外本类中将执行部分的存储功能,包括初始化时候读出记录数据等。ASprite:该类设

27、置出来的主要目的是为了完成对比所有精灵类Y值大小的,对比的目的是为了实现正常的精灵类的重叠关系,如果不进行对比,会出现如下图一的情况: 图一 图二即是说,按照正常的顺序,靠近我们(也就是在屏幕中Y值更大的,原点在屏幕的左上角,往右为X正方向,往下为Y正方向,和在数学中的坐标的Y不一样)的应该把远离我们的盖住,即图二所示情况,为了实现这样的效果,需要根据每个精灵的Y值对精灵类进行排序,然后在线程每次执行的时候按照排好的顺序进行绘图,如果不定义本类,则无法进行比较,定义本类之后,所有的精灵都从本类派生出去,就能以本类进行比较了。HeroSprite:英雄类,实现英雄的描绘,在单机版中,本类只会实例

28、化一个对象,即玩家操纵的角色,本类的功能在于定义英雄的属性以及英雄的部分描绘方法,这里有一个问题,关于碰撞判定以及之后的精灵类的扣除HP以及其他处理,到底应该放在哪个类中?按照一般的考虑方法,可能会考虑,如果英雄类捕获到了怪物类的攻击判定,那么就把相关的处理方法放到英雄类中,而相应的,怪物类的被攻击的情况就放到怪物类中,然而却有这样一个问题,怪物受到英雄类的攻击当然比较好检测,因为在单机版中英雄只有一个,每次只需要判定这么一个英雄是否攻击了该怪物类就行了,然而英雄类那边却不行,不可能让英雄类来遍历一次目前所有的怪物中哪个怪物攻击了英雄,这在手机上是巨大的资源消耗,是行不通的。所以,只能把所有的

29、碰撞以及相应处理都放在怪物类中,包括对英雄的攻击后的处理。所以剩下的英雄类所做的事情其实相比怪物类来说已经简单了很多,主要是接受键盘输入的控制,以及相应的描绘,另外还有判定下一步的地图是否可以跨越,以及每次关于要存储进RMS中的数据的更新等。MonsterSprite:怪物类,实现怪物的描绘,应该能接受一些重要参数(比如等级)以实现怪物的不同能力,以及具有一定的人工智能,另外有如前所述的具有双方攻击判定以及相应的处理方法。本次游戏中的怪物对比上一次我们参加康菲杯制作的游戏中的怪物要“聪明”上许多,在不遭受攻击的情况下,会根据前方地图是否可以跨越然后慢无目的地四处溜达,在遭受攻击情况下,会一直追

30、着主角打,除非距离已经拉开了很长一段。可以说怪物类是本游戏单机版本中游戏逻辑的核心。3、网络版Server:主要还是不停的接受玩家的连接信息,连接上来后实例化Client,由它来处理玩家的各种请求。Client:当一个客户登陆上来以后,先验证该用户信息的有效性,合格以后发送登陆成功的消息到客户端,然后将已经在游戏中的玩家ID发送给该客户,该客户接受到这些ID后在OtherHeroSprite中实例话这些用户。服务器还自动的将刚刚登陆上来的这位玩家的ID发送给其他完家。当完家在移动的时候,将完家的坐标发送给其它玩家。GameClient:连接上服务器后,若登陆成功则实例化SFCanvas,玩家进

31、入游戏界面,然后GameClient不停的监听来自服务器的消息。同时处理客户端发给服务器的信息OtherHeroSprite:处理其它完家的信息,当有一个玩家登陆上来以后,GameClient接受到该客户的Id,然后传到OtherHeroSprite,由OhterHeroSprite实例化该类。当该玩家移动时候,OtherHeroSprite接受到该玩家的新坐标,刷新坐标,将该玩家画到新的坐标七、编码实现1、Tales类以及生命周期的实现Tales类直接继承自MIDlet,沿用规范直接实现生命周期,另外该类实例化SFCanvas实现低级绘图容器,在重载方法protected void paus

32、eApp()中实现游戏暂停的相应处理。具体来说,单机版暂停线程运行,网络版直接退出游戏。2、FCanvas类、地图切换,坐标转化以及界面要素的实现SFCanvas类中主要是执行初始化,线程控制以及其他类的实例化,精灵类层叠次序的排序,类之间的通信,另外还包括相当部分界面的描绘,以及RMS数据的读取。由于精灵类中将描绘和构造函数分离,所以在SFCanvas的构造函数中先对各个精灵类进行初始化,然后在线程中进行相应的描绘,值得注意的是为了尽量节约内存资源,线程中应尽量只描绘当前画面的精灵和地图,在MIDP2.0中提供了一个LayerManager类对层进行管理,如果将精灵类和地图都加入到Layer

33、Manager所管理的图层中,则该类会自动进行相关处理,描绘将只在屏幕范围内进行,但该类有个缺陷,就是一旦规定了图层层叠顺序就无法在线程运行过程中改变,天空层(可以将精灵类遮盖的层,比如树木,云层等等),地面层(地图)倒是固定好了的顺序可以用LayerManager来管理,但精灵就不行了,如前文所述,精灵类的层叠顺序是按照精灵的Y值大小来进行排序的,所以,最后程序采用了天空层,地面层用LayerManager管理,而精灵则采取Graphics类直接描绘。关于精灵的排序也是在本类的线程中实现的,其代码如下:/首先将要排序的精灵类都放入一个精灵类的数组mspublic ASprite chgMon

34、sterOrder(ASprite ms)for(int l=0;l<3;l+)for(int m=0;m<3;m+)if(msm.dy>msm+1.dy)/根据Y值排序,本段采用了最简单的冒泡排序法tempMonster=msm;msm=msm+1;msm+1=tempMonster;return ms;/返回排序后的数组ASprite ms1 = monsterSprite, monsterSprite1, monsterSprite2, heroSprite;/将需要排序的精灵纳入数组ASprite ms2=chgMonsterOrder(ms1);/将排序完成后的数组

35、赋值layManager.paint(g,0,0);/对层管理类进行描绘for(int h=0;h<4;h+)ms2h.setPosition(ms2h.dx-setX,ms2h.dy-setY);if(ms2h.dx<(getWidth()+setX) && ms2h.dx>setX &&ms2h.dy<(getHeight()+setY)&& ms2h.dy>setY)/只对进入屏幕范围类的精灵才进行描绘ms2h.paint(g);/对精灵类进行描绘下面介绍下关于在本类中实现的关于怪物类和英雄类的通信,如设计中所

36、述,关于攻击判断都是放在怪物类中写的,所以,英雄受到攻击后削减HP以及打败怪物后所获得的奖励等等都只能依靠类之间的通信来实现,这里我们采用了参数返回和传递的方式,即怪物类返回一些参数,而将这些返回的参数直接传递给英雄类,让英雄类实现各类数据的更新并且在更新后立即将新的数据存入进度。具体的实现代码如下:/将怪物类的死亡后的等级以及各方面信息传递到英雄类private void doMonster(MonsterSprite mSprite,HeroSprite heroSprite,RecordStore rs,int rid)heroSprite.doMonster(mSprite.doMov

37、edraw(heroSprite.x+heroWidth,heroSprite.y+heroHeight,getHeight(),getWidth(),heroSprite.dir,heroSprite.iisBattle,heroSprite,heroSprite.hp,heroSprite.lv,heroSprite.itemlv),mSprite.deadlv,rs,rid);看起来比较复杂,让我们将他们分解一下,在MonsterSprite类中有一个方法.主要用于描绘和相应的游戏逻辑处理,public int doMovedraw(int heroX,int heroY,int scr

38、eenHeight,int screenWidth,int heroDir,boolean iisBattle,HeroSprite heroSprite,int heroHp,int herolv,int itemlv),关于该方法的详细解释会在怪物类的代码实现中有解释,它拥有一个int的返回类型,在该方法中,返回的是英雄的HP值,而我们也可以看到传入的参数中也有英雄的HP值,即这个方法中实现了怪物的描绘和英雄类HP的变化,同时在怪物类中具有一个属性deadlv,如果怪物处于生存状态,该值一直为0,在怪物类的doMovedraw()方法中如果怪物死亡就立即将该值赋为怪物等级,而相应的英雄类中

39、处理怪物传来的信息的方法就捕获到该值,然后就对英雄类的属性进行更新,将更新值存入进度.接下来再介绍一下如何将进度存入RMS中,RMS即Record Management System,是由MIDP提供的数据存储功能,使用这个功能,就可以存储游戏状态,关于RMS的详细内容请有兴趣的朋友查阅相关资料,这里我们这种讲述如何实现进度的存储,实际上由于RMS的存储功能远远不如大型的数据库功能完善,所以很多地方需要自行设计许多东西来达到方便的记录管理,RMS的存储是逐条地操作,而一条记录并不存在如大型数据库中的字段类的概念,所以,为了实现类似的功能,只能在程序中将的所有数据一次操作。J2ME中提供了对二进

40、制数据进行操作的DataOutputStream类和ByteArrayOutputSteam类,通过这两个类可以很方便地把各种类型的数据转换为二进制数据并存储在一行记录中,例如游戏中英雄类的一次记录操作包括记录他的等级,当前的装备,拥有的金钱,物品盒中的物品,经验值等,它们的类型有的是String,有的是int,就可以按如下的程序实现二进制数据到真实数据的转化:/对记录中的数据进行转化public static void chgTogame(byte data,HeroSprite heroSprite) throws IOExceptionByteArrayInputStream bais=

41、new ByteArrayInputStream(data);DataInputStream dis=new DataInputStream(bais);heroSprite.lv=Integer.parseInt(dis.readUTF();heroSprite.itemlv=Integer.parseInt(dis.readUTF();heroSprite.gold=Integer.parseInt(dis.readUTF();heroSprite.MyItem=dis.readUTF();heroSprite.exp=Integer.parseInt(dis.readUTF();hero

42、Sprite.at=(heroSprite.lv-1)*8+30;heroSprite.df=(heroSprite.lv-1)*10+20;System.out.println(heroSprite.MyItem);heroSprite.itemcode=heroSprite.MyItem.toCharArray();为了实现记录读取的效果,在此之前需要从进度中将记录读取出来而在记录实际使用时:try/尝试获得记录rs=RecordStore.openRecordStore(dataname,false);/如果不成功则不创建try/成功后则尝试获取记录heroData=rs.getReco

43、rd(1);chgTogame(heroData,heroSprite);/将记录转化为实际数据isData1=true;catch(Exception e)System.out.println("没有获得记录"+e);catch(RecordStoreNotFoundException e)/如果没有成功获得try/关闭记录System.out.println("没找到记录");rs.closeRecordStore();rs=null;isData1=false;catch(Exception ex)catch(Exception e)接下来向大家介

44、绍一下地图切换的具体实现,地图切换在这里我专门使用了一个方法来实现,该方法以地图编号为参数,进行实例化以及相关垃圾处理,具体代码如下:public void gotoMap(int mapDir)if(mapDir=0)/图1的对象撤消,具体是将其赋为NULLtry/描绘新地图/图0要用到的图片加载catch(Exception e)/实例化地图0要使用的对象else/图0的对象撤消,具体是将其赋为NULLtry/描绘新地图/图1要用到的图片加载catch(Exception e)/实例化地图1要使用的对象而具体的地图描绘操作则是如下代码:mapTiled=null;heroSprite.is

45、Walkable=null;/清空地图1资料mapTiled=new MapTiled(30,30,mapImage,16,16,getWidth(),getHeight();/加载新地图资料mapTiled.drawMap(mapDir,setX,setY);heroSprite.chgMapbool(mapTiled.isWalkable0);layManager.append(mapTiled);这里的setX,setY是将相对于地图左上脚的屏幕左上脚的坐标:(地图一的情况下)setX=heroSprite.x-getWidth()/2+20;/地图画的位置的左上脚坐标setY=hero

46、Sprite.y-getHeight()/2+20;if(heroSprite.x-getWidth()/2+20<=0)setX=0;if(heroSprite.x-getWidth()/2+20>=625-getWidth()setX=625-getWidth();if(heroSprite.y-getHeight()/2+20<=0)setY=0;if(heroSprite.y-getHeight()/2+20>=625-getHeight()setY=625-getHeight();而实际上这里的setX,setY在坐标转化的过程中作用巨大,一方面实现了主角走到

47、边角人物移动而地图不移动的效果,另一方面也实现了绝对坐标和相对坐标的转化,具体的如精灵类,怪物类的坐标如下:ms2h.setPosition(ms2h.dx-setX,ms2h.dy-setY);转化方式如下图:地图屏幕setXsetY精灵dxdy由此可见,相对坐标是(dx-setX,dy-setY)决定的,而dx,dy则是ASprite类定义的精灵类的公有坐标属性.由此即可实现相对屏幕左上的坐标和相对地图左上坐标的转化。3、HeroSprite类以及键盘事件,进度更新的实现HeroSprite类主要实现英雄的相应处理,包括对英雄的相应记录的更新,以及对事件的处理,另外包括对不能行走地图的检测

48、。首相,对记录的更新,具体实现如下:public byte chgTorms(boolean isFirst) throws IOExceptionByteArrayOutputStream baos=new ByteArrayOutputStream();DataOutputStream dos=new DataOutputStream(baos);if(itemcode!=null)MyItem=String.valueOf(itemcode);dos.writeUTF(String.valueOf(lv);/将具体数据写入流dos.writeUTF(String.valueOf(item

49、lv);dos.writeUTF(String.valueOf(gold);dos.writeUTF(String.valueOf(MyItem);dos.writeUTF(String.valueOf(exp);if(isFirst=false)/如果不是第一次读入数据则计算攻防at=itematitemlv+(lv-1)*8+30;df=itemdfitemlv+(lv-1)*10+20;baos.close();dos.close();numEmpty=0;if(isFirst=false)/如果不是第一次读入数据则计算空格数for(int i=0;i<itemcode.lengt

50、h;i+)if(itemcodei='0')numEmpty+;return baos.toByteArray();对怪物的相应处理函数从SFCanvas中获得数据,这一点在之前的SFCanvas中已有叙述,具体实现代码如下:public void doMonster(int myhp,int deadlv,RecordStore rs,int recordid)this.hp=myhp;if(lv<=6)prevexp=lv*lv*60-(lv-1)*(lv-1)*60+150;/经验值公式nextexp=prevexp+(lv-1)*(lv-1)*60-(lv-2)*

51、(lv-2)*60+150;elseprevexp=lv*(lv-5)*(lv-5)-40*(lv-4)*(lv-4)+150;nextexp=prevexp+50*(lv+1)*(lv-4)*(lv-4)-40*(lv-3)*(lv-3)+150;if(deadlv!=0)exp=exp+deadlv*15+random.nextInt()%5;/怪物死亡时候等级和经验值的换算公式,nextexp下一等级需要的经验,deadlv被杀死怪物的等级if(exp>=nextexp)if(lv<12)/目前设定的最高等级为11级lv+;at=itematitemlv+(lv-1)*8+3

52、0;df=itemdfitemlv+(lv-1)*10+20;maxhp=160+(lv-1)*40;hp=maxhp;tryrs.setRecord(recordid,chgTorms(false),0,chgTorms(false).length);catch(Exception e)System.out.println(e);isBattle=false;关于地图可行与否的判断中会遇到如下问题:如上图,英雄贴着墙站着,而且下一步他就会进到墙里面。我们不会让它发生的。当然在这里可以设置他即将进入的方块的可行性为false,在向左行走时进行判断主角下一步即将进入的方块可行性,如为FALSE,

53、则不进行坐标和帧变化,实际体现出来的效果就是不能行走,但在实际情况中往往没有这么理想,他可能会产生如下情况:由图可见,如果仅仅判断精灵类的左上脚,在这样的情况下,显然他的下一步是可行的,但实际上该精灵因为左下脚被挡住,已然无法前进,因此在这样精灵向左走的情况下,实际是要检查左上和左下两个地方是否都可以行走的,如果其中有一个不满足则不能前进,与此相似,如果在向右走的过程中,则需要同时检查精灵的右上和右下脚,其他的则以此类推,具体实现代码及解释如下(仅解释UP键):case LISTENER_UP:if(dir!=DIR_UP)/如果按下UP键时之前的状态不是朝UP的话,则改变状态dir=DIR_

54、UP;this.setFrameSequence(up_seq);if(isWalkableldXldY-1 && isWalkablerdXrdY-1) /对下一步的判断,如前所述if(isBattle=true)/按下UP键时候如果是打斗状态则转化为UP奔跑帧this.setFrameSequence(up_seq);isBattle=false;if(isStop=true)/如果是停止状态也转化为UP奔跑帧this.setFrameSequence(up_seq);isStop=false;y=y-5;/坐标变化this.nextFrame();/帧变化break;关于ldX,ldY等则是左下坐标,rdX,rdY则是右下坐

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论