4 程序分析和具体实现 4.1 游戏进入前的选择 copyright paper51.com
每个MIDlet程序都必须有一个主类,该类必须继承自MIDlet。它控制着整个程序的运行,并且可以通过相应函数从程序描述文件中获取相关的信息。该类中拥有可以管理程序的创建、开始、暂停(手机中很可能有正在运行程序却突然来电的情况,这时应进入暂停状态。)、结束的函数。本程序主类为lzhhdm,并实现接口CommandLIstener。 copyright paper51.com
http://www.paper51.com http://www.paper51.com 首先显示的是游戏的背景介绍(图4-1),为此,在类lzhhdm定义Form类对象a,在startApp()函数中判断isSplash是否为真,如果为真的话,将创建Form类的实例a,并且调用append()方法在表单上放置StringItem类的实例以显示游戏背景信息。使用语句ok=new Command("ok",Command.OK,1);实例化Command类对象ok。调用addCommand()命令建立ok命令与Form之间的关联,调用setCommandListener()命令使Form与CommandListener建立关联。调用Displayable的 copyright paper51.com copyright paper51.com http://www.paper51.com 图4-1游戏背景介绍 http://www.paper51.com seturrent()函数显示背景介绍窗口。 http://www.paper51.com 当玩家点击ok后将调用display.setCurrent(menuscreen) paper51.com 以显示游戏菜单menuscreen(图4-2)。 内容来自论文无忧网 www.paper51.com 类menuscreen继承自Canvas类,并实现接口Runnable 内容来自论文无忧网 www.paper51.com 和CommandListener。在类menuscreen中定义了lowColor和 http://www.paper51.com highColor、highBGColor三个整型变量及布尔型变量co。其 内容来自www.paper51.com
中lowColor赋值为0x000000FF,代表兰色,higColor赋值为 copyright paper51.com
0x00FF0000,代表红色,highBGColor赋值为0x00CCCCCC,代表 copyright paper51.com
内容来自论文无忧网 www.paper51.com 图4-2 游戏的菜单 http://www.paper51.com 兰灰色,即背景条。当玩家按住上或下键时,在函数keyPressed paper51.com (int code)中的整型变量menuIndex相应的减1或加1,相应的,在paint()函数中会根据menuIndex绘制选项是否被选中。在函数run()中,如果co为真,则不停的repaint(),设置co的意义在于,当进入游戏主画面后,co赋值为false,以终止绘制选项的repaint(),提高游戏速度。 内容来自www.paper51.com 当移动选项条到某项,并点击ok时,在commandAction()方法中根据 menuIndex paper51.com 的值判断选择了哪个选项,列如当选择“关于”时,将调用lzhhdm类中的renwuShow()方法以显示”关于”界面(图4-3),在renwuShow()方法中,Form类对象a=null,表示清空Form,并重新调用用append()方法在表单上放置StringItem类的实例以显示游戏关于信息,“帮助“界面的显示与”关于“界面相同,只不过调用的是helpShow()方法。 内容来自www.paper51.com
内容来自论文无忧网 www.paper51.com
copyright paper51.com
copyright paper51.com
http://www.paper51.com
copyright paper51.com
http://www.paper51.com
图4-3关于界面 http://www.paper51.com 4.2 mybullets类 内容来自www.paper51.com
在介绍游戏主类gameScreen类之前,应该先简要说明一下玩家子弹类mybullets类,实际上,mybullets类是应该删除的,其要实现的功能应该放在gameScreen类中,但是由于设计游戏的过程也是一个学习的过程,而在当时,我并没有意识到这一点。 paper51.com Mybullets类继承自Sprite类,以实现玩家子弹的相关功能。首先,创建子弹状态数组private int[][] bullets,其中,[i][0]代表子弹的X坐标,[i][1]代表子弹的Y坐标,[i][2]代表子弹Y方向速度,[i][3]代表子弹存活状态(由于此类是在早期设计的,而之后子弹存活状态使用了子弹射程作为标志位,所以其并没有起到作用)。类中定义的方法setfirstposition()起到定义玩家子弹发射坐标的作用(此方法在设计时起到的作用是消除每按一次开火玩家子弹位置就重新定位这个BUG,但是,这个BUG完全可以用设置标志位的方法消除)。方法newposition()实现的功能为更新玩家的子弹位置,并且检测玩家子弹与普通敌人的碰撞及记录玩家战果(更新子弹位置的功能可以由使用move()加设置标志位的方法取代;由于设计这个类的时候并没有考虑到添加BOSS等,所以在此检测碰撞,但添加BOOS等功能后,此处的检测完全可以和飞机对飞机等的碰撞检测封装在同一个方法中)。 copyright paper51.com
mybullets类在gameScreen中建立了对象数组huokebullet[9],代表玩家所能发射的9发子弹。 paper51.com
4.3 游戏逻辑及gameScreen类 内容来自www.paper51.com gameScreen类是游戏的主类,决定着敌人何时出现,控制着敌人出现的方法,判断敌人及玩家是否被击中等。它运行在独立的线程中,以恒定的频率刷新画面。本程序设置为1/20秒。其主逻辑如图4-4所示。 copyright paper51.com
4.3.1 gameScreen类所实现的功能 paper51.com gameScreen类要实现地图的滚动、敌人飞机的相关属性、玩家的相关属性等功能。 copyright paper51.com gameScreen类包括了LayerManager,这样所有静态和动态的图象都不需要手动刷新,只需要在LayerManager中加入所有的需要控制的精灵,在统一由LayerManager刷新即可, 因此,在gameScreen中创建LayerManager的对象lm,并在构造函数中实例子化。 paper51.com
其他精灵类的对象如敌人飞机、玩家飞机、玩家飞机的子弹、敌人的子弹、BOSS及BOSS所属的子弹都需在gameScreen()类中建立相应的对象,并在构造喊数中实例化,且由lm.appned()方法添加到LayerManager类对象lm中。 内容来自论文无忧网 www.paper51.com
4.3.2 地图的创建 http://www.paper51.com
由于手机存储空间的限制,不可能将整张地图完整地存储在手机中,为了节约空间,往往提出地图中相同的图片组成一张PNG格式的图片,然后象拼图一样拼出地图来,专业的游戏设计者往往自己写一个地图编辑器,以使拼图过程不是那么痛苦。 内容来自www.paper51.com
创建地图就需要使用TiledLayer。TiledLayer指的是由一块一块类似用瓷砖拼凑起来的画面。地图实际即为TiledLayer的一个对象。先利用TiledLayer的构造函数建立TiledLayer,根据构造函数的参数可以给定Cell数组 的大小,并且地图图片切割成等尺寸的画面,并调用setCell()设置具体的图象格内容。地图 paper51.com http://www.paper51.com 图4-5 地图 paper51.com
内容来自论文无忧网 www.paper51.com 图片如图4-5所示。 paper51.com 因此,创建一个返回TtiledLayer的方法createBackGround(),以便在gameScreen()的构造函数中调用。在方法中,定义整型数组map1[]以存储Cell的索引值。并使用tiledLayer.setCell(column,row,map1[i])设定TtiledLayer的内容,以形成地图。其中i的值由循环for(int i=0;i<map1.length;i++)取得,column由语句column=i%15取得、行由row=(i-column)/15取得。 copyright paper51.com 画出地图后,由lm.append()将地图添加到LayerManager类对象lm中。由于地图位于Layer的最低层,即离用户视线最远的层,所以Tiledlayer最后一个被添加到lm中。 copyright paper51.com 4.3.3地图的移动 paper51.com 根据游戏的设定,游戏中地图是向下移动的,实现此功能的方法如下: 内容来自论文无忧网 www.paper51.com 首先,在使用createBackGround()函数创建地图数组时,用(row+1)*16-getHeight() 内容来自论文无忧网 www.paper51.com 语句对整型变量row2赋值,其中row+1代表地图有多少列,16为地图片的高度,而减去getHeight()是因为要留出一个屏幕的可视区域,由于J2ME规定坐标系中下方向为正,所以使用语句y1=-row2将row2的数值变为负数。 http://www.paper51.com paper51.com paper51.com (0,y1) paper51.com y1=y1+1; 内容来自www.paper51.com View Window http://www.paper51.com 向下移动 paper51.com (0,0) paper51.com
copyright paper51.com 图4-6 内容来自www.paper51.com
http://www.paper51.com 图4-6 paper51.com
paper51.com
其次,render()函数中,使用lm.setViewWindow(0,0,getWidth(),getHeight()+10000)设定可视区域的范围,(0,0)表示View Window的起始坐标,(getWidth() ,getHeight()+10000) 内容来自www.paper51.com
使用lm.paint(g,0,y1)决定 paper51.com
View Window从屏幕的哪里画起。 内容来自论文无忧网 www.paper51.com
在run()函数中的while(conti)中, paper51.com
copyright paper51.com
屏幕 http://www.paper51.com 使用语句y1=y1+1使得每次绘图都使 内容来自论文无忧网 www.paper51.com 地图下移1个象素。(参考图4-6) paper51.com 4.3.4 gameScreen类的构造函数 http://www.paper51.com gameScreen类的构造函数要将游戏中出现的所有精灵都实例化,实际上,这种方法 paper51.com 严重的占用了内存,但在当时,我并没有意识到这一点。 paper51.com 由于敌人要求不停的出现,但是不可能设置过多的精灵,解决的办法是设定6个Sprite类对象j0、j1、j2及jbullet1、jbullet1、jbullet2,分别代表三架敌机及其配属的子弹。所以在gameScreen类的构造函数分配这6个Sprite类的存储空间,并且使用new Sprite(Image img, intwidth,int height)实例化这6个类变量。同关尾cboss与游戏进行中的大飞机其他的Sprite类对象都需要使用相同的方法实例化。同样处于节约内存的考虑,sboss与cboss同用3个Sprite类对象bossbullet0,1,2。 http://www.paper51.com
在构造函数中,定义boolean型变量conti=true。conti的作用在于控制是否进行游戏画面的重绘及其他需要在画面重绘前进行的运算。 内容来自www.paper51.com 在构造函数中,将mybullets类里的no和score初始化,现在看来no的初始化没有必要,但是score的初始化是必须的,因为这个变量存储着玩家每次游戏的成绩,如果不在此进行初始化,则玩家重新开始游戏后score并不归0。 http://www.paper51.com
|