基于J2ME的手机游戏逃亡者的设计与实现_第1页
基于J2ME的手机游戏逃亡者的设计与实现_第2页
基于J2ME的手机游戏逃亡者的设计与实现_第3页
基于J2ME的手机游戏逃亡者的设计与实现_第4页
基于J2ME的手机游戏逃亡者的设计与实现_第5页
已阅读5页,还剩67页未读 继续免费阅读

下载本文档

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

文档简介

毕业设计(论文)第1页共42页目录 11.1国内外手机游戏的研究现状 11.2手机游戏的技术分类 11.3研究意义 2 42.1什么是J2ME 42.2J2ME平台体系结构 4 5 6 8 8 9 3.1手机游戏的画面 3.2手机游戏中的按键 3.4手机硬件平台特点 3.3线程使用 3.4手机硬件平台特点 3.5手机游戏开发工具软件 4.1游戏描述 4.2可行性研究 4.3游戏设计 4.4详细编码设计 4.5程序打包、下载安装与运行 4.6最后效果图 第1页共42页第一章引言近年来,因特网在国内迅速普及,导致了网络游戏的高速发展。同样手机的普及,导致了手机游戏市场呈现爆炸式的发展。尤其是国内外巨大的手机拥此巨大的手机游戏市场,各游戏开发商、运营商、服务商以及手机终端厂商等的性能,同时还在手机操作系统方面采用开放式的平台,方便用户享受不同的手机游戏业务1。而国内游戏开发商,如盛大、网易等公司,纷纷跻身手机游戏开发商行列。新浪、搜狐等著名的门户网站,也纷纷涉足手机游戏领域,相继开辟了各自的手机游戏频道和栏目,其他一些游戏网站也都全面加快了手机游戏开发的步伐。目前SUN公司的J2MECLDC/MIDP环境和高通公司的BREW(BinaryRuntimeEnvironmentforWireless)客户端程序是国内外游戏开发的等丰富的数据服务。中国移动用户只要使用支持Java的手机,通过GPRS的无Java语言编写的应用程序。而中国联通与高通公司合作,采用高通公司的1.2手机游戏的技术分类手机游戏按实现的技术分,可分为嵌入式游戏、浏览器游戏、基于J2ME能,从而达到其他类型的游戏所无法达到的效果,而且嵌入式中不会让用户产生费用。但是这些游戏是依据手机生产厂商的平台进行开发毕业设计(论文)的,出厂时设置了几款游戏,玩家就只能在这几款游戏当中进行选择,而不能根据用户自己的喜好对游戏进行升级、删除等操作,所以嵌入式游戏的缺点也是明显的,无法给玩家带来新鲜感,玩家容易对固定的几款游戏产生厌倦。WAP是一种用手机上网的网络服务。进行WAP游戏时,通过手机自带的WAP浏览器来浏览手机网站上的页面,并通过页面中描述的内容来进行游戏。形式上类似于网上常见的一些心理测验之类的交互手段。WAP游戏没有图片和容量的限制,但这类游戏大多采用文字交互方式,这样游戏性就不强,缺乏直观感觉。而且在收费上,WAP游戏费用比较高,因为在游戏的过程中,您不仅需要向服务商交纳一定的费用,而且同时要向中国移动或中国联通交纳一定的使用C++应用程序和其它编译语言开发游戏也是一种较好的开发方式。编译语言程序能提供更好的控制用户界面,而且编写的应用程序相比用脚本语言编写的程序,效率更高、使用的内存更少,并且执行得更快。但由于这些编译语言往往不具有跨平台性,而且由于编译语言的特点,往往需要较长的开发周Java2MicroEdition(J2ME)是一种针对移动电话和PDA等小型设备的Java语言。采用J2ME极大的提高了手机支持游戏的能力。它有比WAP游戏更易控制的界面,J2ME游戏摆脱了纯文字交互的方式,它允许使用图形动画,并且可以通过无线网络连接到远程服务器。而且Java是面向对象程序设计的语言,它最大的特点是一次编写、到处运行,即平台无关性。现在支持Java的手机比较普及,它也已经成为目前比较好的移动游戏开发环境。手机游戏成了电信增值业务中一项主要的应用,在公交车等公共场合不时游戏,如今的手机游戏,无论是从视觉效果、听觉效果还是游戏的可玩性来说,都要精彩的多。在全球,移动电话数量巨大,除美国之外,其他各个发达国家拥有手机的人数比拥有计算机的人数还多。在我国,手机拥有量甚至超过了美国的人口数量,而且每个月手机数量还正以惊人的速度递增着。手机市场的高速增加带动了手机游戏市场的急速膨胀,基于JAVA、BREW等技术平台第3页共42页的手机游戏市场规模纷纷呈现几何增长态势[2]。第4页共42页J2ME是SUN公司针对嵌入式、消费类电子产品推出的开发平台,与J2SE和J2EE共同组成Java技术的三个重要的分支。J2ME实际上是一系列规范的集合,由JCP组织制定相关的JavaSpecificationRequest(JSR)并发布,各个厂商会按照规范在自己的产品上进行实现,但是必须要通过TCK测试,这样确保J2ME平台是由配置(Configuration)和简表(Profile)构成的。配置是提供给最大范围设备使用的最小类库集合,在配置中同时包含Java虚拟机。简表是针对一系列设备提供的开发包集合。在J2ME中还有一个重要的概念是可选包(Optional-Package),它是针对特定设备提供的类库,比如某些设备是支持蓝牙的,针对此功能J2ME中制定了JSR82(BluetoothAPI)提供了对蓝牙的支持。目前,J2ME中有两个最主要的配置,分别是ConnectedLimitedDevicesCDC的硬件参数:(1)2M以上内存。(3)需要实现java虚拟机规范的全部功能。(4)32位或者64位的处理器。(1)512KB以下内存(2)有限能源供应(通常使用电池)。(4)简单的用户界面。(5)16位或者32位的处理器。车导航系统等。简表是以配置为基础的,例如MobileInformationDevicesProfile(1)主机操作系统层(HostOperatingSystemLayer):这一层为特定硬件设备的操作系统层。(2)Java虚拟机层(JavaVirtualMachineLayer):这一层是Java虚拟机的一个实现,它是为特定为特定设备的主机操作系统定制的,支持一个特定的J2ME配(3)配置层(ConfigurationLayer):配置层定义Java虚拟机的功能和特定类别设(4)描述层(ProfileLaver):描述层定义了特定类别设备上可用的应用程序编层、配置层和描述层。的核心,只要Java程序在执行,Java虚拟机也必定在执行。Java虚拟机是实际执行Java程序的引擎,也是Java语言具有这么多优良特色的关键所在。当你执行Java程序时,程序内的指令其实并不是由硬件直接执行,而是由一个特别的软第6页共42页件一一读取这些指令来执行的。简单地说,Java程序不是被特别软件。虚拟机的优点甚多,比如移植方便,只需要移植虚拟机和相关的支持程序库到新的硬件架构上,所有上层的应用程序都不需要更动就完成移植可以防止恶作剧的程序暗中搞鬼[S。2000年5月,JavaCommunityProcess(JCP)公布了CLDC1.0规范(即JSR30)。作为第一个面对小型设备的Java应用开发规范,CLDC是由包括Nokia,Motorola和Siemens在内的18家全球知名公司共同协商完成的。CLDC是J2ME核心配置中的一个,可以支持一个或多个profile。其目标主要面向小型的、网络连接速度慢、能源有限(主要是电池供电)且资源有限的设备,如手CLDC的核心是虚拟机和核心类库。虚拟机运行在目标操作系统之上,对需求。2虚拟机可选包2.4.1CLDC的目标2.4.2CLDC的整体需求(1)能运行在绝大多数的小型的、资源受限的连接设备上。第7页共42页2.4.3CLDC的硬件需求由于CLDC要面向尽可能多的设备,而这些设备所使用的硬件又各不相同。因此CLDC规范中并没有指明需要某种硬件支持,只是对设备的最小内存(1)至少160KB的固定内存以供虚拟机和CLDC核心类库使用。(2)至少32KB的动态内存以供虚拟机运行时使用(堆栈等)。体的设备的具体实现,这些需求也可能有变化。这里所规定的160KB是CLDC规范中的要求,实际也可以是128KB左右。2.4.4CLDC的软件需求和硬件类似,CLDC上运行的软件也是多种多样的。例如,有些设备支持多进程操作系统或者支持文件系统;而有些功能极其有限的设备并不需要文件系统。对于这些不确定性,CLDC只定义了软件所必须的最小集合。CLDC规范中要求操作系统不需要支持多进(1)Java核心语言与Java虚拟机的特性(2)核心Java类库(3)输入/输出(1)安全(3)遵守Java虚拟机规范(4)要求类文件验证J2EE和J2SE为桌面计算机和服务器的企业级应用和开发提供了非常丰富的库函数。不幸的是这些库需要几十兆的内存来运行,因此并不适合于资源受限的小型设备。所以CLDC针对小型受限设备重新制定了一个类库。为了保证应用程序的兼容性和可移植性,包括进CLDC的大多数类库都是J2SE中规定的子集,其它一些是由CLDC规定的专用于移动设备的类。包括:从J2SE中继承的第8页共42页J2ME提供了描述的概念,使得可以为特定的设备家族定义相同的Java平(1)描述为在一个特定的设备家族实现应用提供了完整的工具,比如传呼机、机(2)可以创建一种描述来支持重要的、一致的一组应用,这些应用可能会在几各简单地说,描述就是应用和市场的设备家族之间的协议。处于同一个设备家族中的所有设备都必须实现其描述所定义的特征,并且要求应用只使用这个特定描述所提供的功能。在实现层次上,描述被简单地定义为应用在特定配置上的JavaAPI和类库的集合,同时为市场中特定的设备家族提供了附加的面向特定领域的功能17]。表2-1五个规范化描述CLDC和MIDP组合起来为创建移动电话应用程序提供了完整的环境。MIDP应用程序或者称为MIDlet.其模型如图2-3所示基于J2ME的手机游戏设计第9页共42页MIDlet有三个状态,分别是pause、active和destroyed。在启动一个MIDlet的时候,应用管理软件会首先创建一个MIDlet实例并使得他处于pause状态,当startApp(方法被调用的时候MIDlet进入active状态,也就是所说的运行状使得MIDlet进入destroyed或者pause状态。值得一提的是destroyApp(booleanunconditional)方法,事实上,当destroyApp()方法被调用的时候,AMS通知MIDlet进入destroyed状态。在destroyed状态的MIDlet必须释放了所有的资知后抛出MIDletStateChangeException而保持在当前状态,如果设置为true的话,则必须立即进入destroyed状态。下图2-4说明了MIDlet状态改变情况:pauseAppIn组件与低级绘制相比,用在游戏开发上的机会较少,但还是会到。所谓UI组件,是指继承了javax.microedition.lcdui.Screen类的javax.microedition.ledui.Alert,javax.microedition.lcdui.Form,javax下图为我们展示了整个LCDUI包的体系:毕业设计(论文)第10页共42页Screen类属于高级图形用户界面组件,Canvas是低级图形用户界面组件,在同一时刻,只能有唯一一个Screen或者Canvas类的子类显示在屏幕上,我们可以调用Display的setCurrent()的方法来将前一个画面替换掉,我们必须自行将前一个画面的状态保留起来,并自己控制整个程序画面的切换。同时我们可以运用javax.microedition.lcdui.Command类来给我们的提供菜单项目的功能,分别Command.STOP,我们在Displayable对象中定义了addCommand()和removeCommand()两个方法,这就意味着我们可以在高级UI和低级UI中同时使用Command类,同时我们通过注册Command事件来达到事件处理的目的,即与高级UI相比,低级UI就自由很多,任何时候我们可以调用repaint()产生重绘事件,调用完了repaint()会立刻返回,调用paint()回调函数则是由另一个专门的线程来完成。底层事件大致可分为三类:PressEvents(按键事件),ActionKeys(动作按键,PointerEvents(触控事件)。键事件的几个核心方法为:keyPressed(),keyReleased(),keyRepeated(),当按键按下时会触keyPressed(),当松开按键时,会触发keyReleased(),当长时间按住按键时会触keyRepeated(),但是RepeatEvents不是JTWI要求强制支持的,所以使用之前要进行测试,看设备是否支持。在Canvas里面我们每按下一个按键都会触发keyPressed()函数,并传入相应位置的整数值,我们在MIDP规范中可以很容易的发现,KEY_NUM0—KEY—NUM9十个常数分别代表键盘上的0-9还有两个功能键,KEY_STAR,KEY_POUND,如果我们传入的值小于0,代表我们传入了不合法的keycode,某些机器上还支持连续按键响应,但这并不是JTWI规定要支持的,所以我们在进行实际开发之前一定要用我们前面讲到的hasRepeatEvents()方法来进行判定。动作按键主要针对游戏来设计的,在API第11页共42页中定义了一系列的动作事件:UP,DOWN,LEFT,RIGHT,GAME_A,触控事件主要面向高端设备,并非JTWI要求强制支持的,其核心方法分别对应我们通常所相应的事件处理函数。在索爱P910C这样的高端手机上,支持屏幕的触控事法和keyPressed()以及keyReleased()大同小异。第12页共42页类中也没有直接操作画面显示的功能。因此,我们要使用提供了管理画面显示javax.microedition.lcdui.Display类的子类显示在画面上。Displayable类的子类大致说来可以分为两种,分别为用来进行线与图形,者是javax.micredition.lcdui.Canvas类后者是javax.microedition.lcdui.Screen类与其子类(Alert,FomList,TextBox类等)之旬的关系。它们之旬的关系如下图3-1:图3-1画面显示类图用来显示画面用的Display对象,可以从Display类的Static方法Display#getDisplay(MIDlet)值获取。通过在获取的Display对象,就可以让Displayable对象显示在画面上。方法,提供了从byte数据中提取Image对象,以及指定与MIDlet相同JAP文件的路径后获取对象的功能。创建Image对象的Static方法:基于J2ME的手机游戏设计上一章提到了MIDPUI的组件,这里不在做解释。Form类是能够将一个以上的图像文本,Item类的子类(ChoiceGroup,DataField,Gauge,Imageltem)混合显示的组件。List类,与PC的UT组件中的List组件一样,是用来显示项目的列表,以让用户来进行选择为目的的组件。也可以是附有选择按钮的列表与附有复选框的列表。文本框是一个允许用户进行编辑的文本区域。一个文本框有一个足以容纳的最大字符数量,具体的大小依赖于不同M工DP的实现或者是移动电话的存储器大小。在文本框中字符显示的顺序和格式由设备决定。当文本框中的字符数量大于一次被显示的字符数量时用户可以通过滚动来编辑一个文本框中的部分字符。Alert,Form,List,TextBox各类的超类Screen由于与类,因此可以用Display#setCurrent3.2手机游戏中的按键在MIDP中,每一个按键事件将产生一个按键代码。在MIDP的Canvas类中定义的按键代码如下所示:KEY_NUMO,KEY_NUM1,KEY_NUM2,KEY_NUM3,KEY_NUM4,KEY_NUM5,KEY_UM6,KEY_UM7,KEY_UM8,KEY_NUM9,KEY_STAR和KEY_POUND。上述按镶代码包括数字0~9、星号和#号。在某些特别的移动设备上可能还有其他按键,但是在MIDP中规定的最低限度的按键就是上面定义的这些。使用这些按键可以确保应用程序在任何符合MIDP规范的移动设备上运行。毕业设计(论文)第14页共42页我们所创建的动画,是使用线程把所准备的多张图像按顺序描绘出来。所谓的线程就是指程序的运行单位,使用线程可以同时进行处理。在这里,为了要做出线程,我们会用到Java.Lang.Runnable接口。同样的处要创建出继承各类的另一个类,所以还不如使用Runnable接口。将Runnable接口作为实现的类,必须将Runnable接口的run()方法重新定在这个run()方法中,将要编写以线程所处理的内容。下面的代码为在run)方法Importjavax.microedition.lcdui.*}~}只在以Runnable接口为实现的类中再定义run(方法,是不能让线程运行的。要运行的时候必须使用到Thread类。要调用Thread类的Constructor中指定Runnable接口参数的constructor,来产生Thread对象。接下来,要用产生的Thread接口来调用Thread#run()方法来启用线程。线程类由于会在Thread#start()方法被调用出来后调用Runnable#run()方法,因此编写在run()方法中的处理将会被自动运行。线程的终止一般可通过两种通常,当一个应用程序停止运行,例如用户从一个主页切换到另一个主页第15页共42页变化。J2MEWirelessToolkit(J2MEWTK)是Sun公司所发布的官方版MIDP应用程序开发工具,它为编写和测试M工DP应用程序提供了一个完整的开发环境。所必需的开发配套元件。成了预验步骤)、打包、模拟运行的菜单(或按钮),以及其它辅助工具。J2SE我们来安装制作JAVA所必需的开发配套元件J2SESDK。先打开读完协议后,选中[Accept]然后再点击[Continue]。试着点击[WindowsInstallation,Multi-language],来下载安装程序。接下来,选择要安装的程序和安装到的地址。这里安装的程序就用默认的程序,安装地址也用默认的[c:\j2sdk1.4.2_05\]。设定数据库文件夹,这里我们也用默认的设置。点击[Next],便开始安装击桌面上“我的电脑”图标,在显示选单中选择“属性”。第16页共42页境变量设定窗口。件夹里“bin”文件夹的路径。这里设定为[c:\j2sdk1.4.2_05\bin]。输完后点击“确下面就让我们来安装手机Java开发元件J2MEWirelessToolkit。打开[Download]按键。看完后选择[Accept],然后点击[Continue]。于是显示安装程序选择画面,点击[WindowsPlatform]的安装程序,并下载。出现WirelessToolkit的安装画面。选择[Next]。设定正在安装的J2SDK的路径。这里点击刚才安装J2SESDK的[Browse..]键,设定[c:\j2sdk\1.4.2_05],设定完后,点击[Next]。接下来设定安装WirelessToolkit的文件夹。这里使用预设的[c:WTK104],在程序文件夹进行注册,这里使用预设的[J2MEWirelessToolkit1.0.4_01],然后点击[Next]。然后是设定的确认画面。若确认正确,点击[Next]。安装完毕后点击[Finish]键,结束安装。Java手机游戏的真实运行环境是Java手机。一般来说,Java游戏的开发是先在第17页共42页为《是男人就撑过30秒》,虽然看似简单,但绝对有挑战性!这是总结了无数色的小点向小飞船聚集过来,小飞船凭借速度优势和飞行技术从黄点之间的夹缝中飞过,之后又落入新的包围圈中,直至被黄点击毁。坚持的时间越长,就说明水平越高。持续不同的时间会得到不同的评价。如图4-1所示是它原来的游戏画面戏画面。的手机游戏设计经验,利用J2ME来可以实现游戏的功能。根据己往的设计进度,一款小型规模的手机游戏大概有2000~3000行代码。于操作[12]。在进入游戏之前先显示闪屏图片,当用户按下键盘或等待3秒后,进入游戏菜单。初始情况下,游戏菜单有三个选项,它们分别是开始游戏,游戏说明和高分记录。选择开始新游戏则进入游戏,在游戏中如果按下非游戏键盘则中断游戏返回菜单,此时菜单中增加了一个继续游戏的选项,可以返回游戏也可第18页共42页以重新开始新的游戏。当游戏结束时则进入游戏结束屏幕,屏幕上显示了玩家的成绩和等级,以及游戏的最好成绩,如果当前成绩是最好成绩,则手机震动并播放音乐庆祝成功。在菜单中选择游戏说明或者高分纪录,则进入相应的屏幕,它们都能用“后退”软键返回菜单。菜单中的退出选闪屏闪屏新游戏游戏说明最高记录继续游戏游戏游戏结束游戏成绩等级最好成绩游戏说明最高记录图4-3游戏系统流程图程序中一个有10个类,其中MIDlet主类负责各个屏幕的切换,它们是闪屏屏幕、菜单、介绍屏幕、高分屏幕、游戏屏幕,游戏结束屏幕。游戏中使用到(逃亡小飞机)。程序的类结构如图4-4所示。Snnn图4-2游戏总体类图第19页共42页游戏的线程主要由三个部分组成:检测键盘输入(与玩家交互),更新游戏场景(处理游戏逻辑),绘制游戏画布。基本上所有的2D游戏都可以按照这三个模块来设计,三个模块相互联系又互相联系,按照模块的思想来实现游戏线程将更加面向对象和便于理解。如果程序运行快于预期速度会使玩家感觉到抖动,从而影响游戏效果,因此还需要检测每帧的运行时间,如果过快则等待检测键盘输入检测键盘输入更新游戏场景绘制缓冲区到否挂起当前线程是挂起等待预期速度绘制游戏画布逃亡者游戏一共实现了几个类包括用于关于游戏外部的闪屏类、菜单类、高分屏幕类、简介屏幕类、结束屏幕类,以及用于游戏本身的游戏画布类、子详情见附录。J2MEWirelessToolkit能自动对MIDlet套件进行打包。打包产生两个文件,即一个MIDlet描述符manifest.mf和一个MIDlet套件JAR。描述符是一个小文本文件,包含有关MIDlet套件的信息。JAR包含组成MIDlet套件的类文件和资源。第20页共42页图4-6游戏运行画面(一)图4-7游戏运行画面(二)图4-8游戏结束画面第21页共42页第五章结束语本文以基于J2ME平台的手机游戏的功能开发为线索,进行了相关理论研究,实验和项目开发。首先介绍了J2ME的用途和基于J2ME平台手机开发的国内外发展情况,然后研究介绍了J2ME平台的特点和手机游戏开发的关键知识1.研究介绍了J2ME平台的用途和基于J2ME平台手机开发的国内外发展情2.研究介绍了J2ME平台的特性和体系结构。重点介绍了MIDP类库,应用游戏角色及游戏流程的控制,对游戏按键事件的处理,并对整个游戏开发过程第22页共42页电子文档,2005-9-5[2]林邦杰·Java程序设计入门教程·中国青年出版社,2001-9-15[16]温尚书·J2ME无线通信实用案例教程·清华大学出版社[18]H.M.Deitel、P.J.Deitel-程序设计教程·清华大学出版社第23页共42页首先感谢我的指导老师罗奇导师,他在我的毕业设计过程中提出了指导性的方案和架构,特别是指引我阅读相关的资料和书籍,使我更能迅速学习掌握知识并完成了这个毕业感谢答辩组对本毕业设计的考核,如果可以得到各位专家的认可将对我的学习和工作给予极大的鼓励。你们客观的评价和建议我将牢记在心,在今后的发展中扬长避短,更加努力的严格要求自己。感谢学校对我的培育,让我从思想上素质上知识上得到很大的提高,本科学习中的各科老师的悉心教导让我掌握了基本知识.感谢我的同学在设计完成前后对我的得力帮助,没有同学的共同学习进步也许就没法完成设计,没有同学对程序的测试,也许就难以发现一些潜在的错误,在此一并表示感在此一并祝愿学校领导、老师、同学工作顺利,事业更上一层楼;同时也祝愿学校更加辉煌。第24页共42页附录根据详细设计对各个类进行编码实现:MIDlet被用作一个状态机来管理各种屏幕以及它们之间的转换。例如,当显示splash屏幕时,该类和类SplashScreen(通过方法splashScreenPainted和splashScreenDone)共同在方法init中完成背景初始化。而使用方法readRecordStore和writeRecordStore在一个名为"BESTTIME"的记录存储区中保存最高得分。(1)实现闪屏Displayablecurrent=Display.getDisplay(this).getCurrent();/获得关于显示的设备上下文Display.getDisplay(this).setCurrent(newSplashScmyCanvas.start();//重新开Display.getDisplay(this).setCurrent(current);//显示游戏画布内容关于闪屏实现的代码如下:newThread(this).start();//启动幕后的初始化线程init();//调用初始化方法privatesynchronizedvoidiif(!initDone)//如果还没有初始化完毕{SoundEffects.getInstance(;//获得声音效果类的唯一实例MenuList(this);//初始化菜单标志位为真表示初始化完毕}第25页共42页init();//检测是否初始化完毕,如果没有继续初始化Display.getDisplay(this).setCurrent(menuList);//在屏幕上显示游戏菜单}(2)屏幕切换从菜单中选择开始游戏,首先初始化Canvas的游戏数据,显示游戏画布,然后启动游戏线程:{myCanvas.init();//初始化游戏数据Display.getDisplay(this).setCurrent(myCanvas);//显示游戏画布myCanvas.start();//启动游戏线程}从菜单中选择显示高分纪录,注意每次都动态生成一个高分纪录屏幕,使用完后就会销毁以避免在不使用的时候占用堆内存:Display.getDisplay(this).setCurrent(newHighScoreScreen(this));//显示高分纪录屏幕从菜单中选择游戏说明,和选择显示高分纪录类似:Display.getDisplay(this).setCurrent(newInstructionsScreen(this));/显示游戏介绍屏幕游戏如果中断,从菜单中选择继续游戏,显示游戏画布并重启游戏线程:{Display.getDisplay(this).setCurrent(myCanvas);//显示游戏画面myCanvas.start);//启动游戏线程从菜单中选择退出,调用quit方法:{quit();//退出游戏从游戏介绍退回菜单,将显示权交还游戏菜单:{Display.getDisplay(this).setCurrent(menuList);//显示游戏菜单}从高分榜退回菜单,将显示权交还游戏菜单:{Display.getDisplay(this).setCurrent(menuList);//显示游戏菜单}从游戏中切换到菜单,需要中止游戏线程并且告知菜单游戏正在进行中,以便让菜单添加继续游戏的选项:myCanvas.stop();//暂停游戏线程menuList.setGameActive(true);//告知菜单游戏已经开始(暂停状态)Display.getDisplay(this).setCurrent(menuList);//显示游戏菜单第26页共42页}显示游戏结束画面,需要告诉GameOverScreen类当前的最好成绩以及子弹的数目,同时告诉菜单游戏已经结束:voidGameCanvasGameOver(longtime,intBULLETS_NUM){myCanvas.stop();//中止游戏线程menuList.setGameActive(false);//告知游戏已经结束Display.getDisplay(this).setCurrent(newGameOverScreen(this画面从游戏结束画面返回,在屏幕上显示菜单:Display.getDisplay(this).setCurrent(menuList);/显示游戏菜单}读取方法的代码如下:privatevoidreadRecordStore()hasBestTime=false;/读取记录还没有获得最好成绩DataInputStream{rs=RecordStore.openRecordStore(RS_NAME,false);//记录名为RS_NAME的字符串bais=newByteArrayInputSdis=newDataIn}}catch(RecordStoreExceptionex)//捕获读取存储记录异常{catch(IOException第27页共42页{除了读取存储之外,如果游戏产生了一个最新成绩,还需要保存到数据存储中去。保存方rivatevoidwriteRecordStore(){RecordStorers=null;ByteArrayOutputStreambaos=null;{rs=RecordStore.openRecordStore(RS_NAME,true);//带开数据存储存如果不存在则创建baos=newByteArrayOutputStream();//输出字节流dos=newDataOutputStream(byte[]data=baos.toByteAr{}{rs.setRecord(1,data,0,data.length);//如果存在记录,则将第一条设置为当前最佳成绩//捕获IO异常}catch(RecordStoreException//捕获数据存储异常毕业设计(论文)第28页共42页/捕获IO异常{rs.closeRecordStore();//关闭数据存储}//捕获数据存储异常获得最佳成绩并保存的实现代码如下:booleancheckBestTime(longtime)if(!hasBestTime||(time>bestTime)//如果还没有最好成绩或者当前成绩比最好成绩长的时{returntrue;//返回true表明对最好成绩进行了更新操作}{returnfalse;//返回false表明没有最新的成绩纪录产生kkf在生成最好成绩之后(无论是读取存储或者玩家在游戏中动态产生的),就需要让游戏结束屏幕或者高分榜知道这个最好成绩:第29页共42页returnhasBestTime?bestTime:-1;游戏的暂停、退出代码如下:{Displayablecurrent=Display.getDisplay(this).getCurrent();//获得当前设备的显示上下文myCanvas.stop();//中止游戏线程myCanvas.stop();//在销毁程序之前先停止游戏线程notifyDestroyed();//告知系统已经销毁程序,可以完全退出}MIDlet中实现了根据字符串类型的文件名来加载图片资源的通用方法,其他各个类都可以returnimage;//返回图片对象image}其代码如下:(mills代表持续的时间。)Display.getDisplay(this).vibrate(millis);//手机震动,持续时间为milliDisplay.getDisplay(this).flashBacklight(millis);//手机背景光闪烁,持续时间为millis}2.游戏闪屏SplashScreen类的实现Splash屏幕在屏幕中央显示图像。在第一次绘制屏幕后,它将图像释放作为垃圾回收(把图片设为null)并回调MIDlet进行初始化工作。三秒钟后或第一次按键后,它再次回调第30页共42页SplashScreen类是一个Canvas类的子类,它的构造函数先获得一个对主类的引用,以便于回调主类的方法,然后加载闪屏图片splash.png,并启动闪屏线程。{splashlmage=escapeeMIDlet.crnewThread(this).start();闪屏屏幕的绘制是在paint方法中完成,当显示闪屏时会自动调用paint方法。注意下面是绘制具有轮廓的文本的有用诀窍:首先用轮廓颜色把它绘制四次,分别向上、下、左、右偏移,然后在它的正常位置用文本颜色对其绘制。在游戏主屏幕中使用该方法要小心,因为文本绘制可能很慢,而该方法使速度减慢为原来的五分之一。publicvoidpaint(Graphicsg)intCanvasWidth=getWidthOintCanvasHeight=get{g.drawlmage(splashlmage,CanvasWidfg.setFont(Font.getFont(Font.FACE_PROPORTIONdrawText(g,centerX,centerY-1);//分别绘制四次,相差1个象素,呈现文本带有背景的感觉drawText(g,centerX,centerY);//绘制文本midlet.splashScreenPainted();//回调midlet的方法,通知程序在幕后做初始化之inttopY=centerY-textHeight/2;//topY用于定位文本的合适位置g.drawString("版本:"+midlet.getAppProperty("McenterX,topY+fontHeight,Graphics.H}第31页共42页(3)闪屏线程闪屏线程的主要工作为接受玩家键盘事件退出或者等待3秒退出,代码如下:{wait(3000L);//等待3秒{//捕获线程中断异常(4)结束线程有两种可能会结束闪屏线程,一为在run方法中线程等待3秒后调用,二为玩家按下键盘,触发键盘事件,调用keyPressed方法,在这个方法中结束闪屏线程。dimiss方法如下,它将回调midlet的splashScreenDone方法,显示游戏菜单:privatevoiddisnmisS(3.游戏菜单MenuList类的实现菜单列表是在splash屏幕之后,或者游戏结束时,或者游戏中用户按下一个非游戏键时(从而暂停了游戏)显示的屏幕。(1)构造函数MenuList类是List类的子类,并且实现了CommandListener接口,它的构造函数为,首先它实现List类的构造函数,然后添加了三个基本选项以及Command:super("逃亡者",List.IMPLICIT);//实现父类List的构造方法,指定List名和选择方式append("开始新游戏",null);/添加新游戏选项(2)继续游戏选项当游戏中间被玩家中止时,游戏菜单中将会多一个“继续游戏”的选项,这个选项添加与否取决于外部传入的布尔值和gameActive值,前者为外部通知菜单游戏是否运行,后者和继续游戏选项是否存在对应(初始情况下为false)。第32页共42页voidsetGameActive(booinsert(0,"继续游戏",null);//在选项顶部插入继续游戏选项ff之(3)处理事件游戏菜单的事件处理包括两种,一种是Command触发的事件,这里为退出程序,另一种是菜单选项的处理处理方式,根据选择不同回调midlet的相应方法,让midlet来负责屏幕的切换。publicvoidcommandAction(Commandc,Displayabled)if(index!=-1)//shouldneverbe-1if(!gameActive)//如果不存在继续游戏选项,则序号往后移位,以便和case选项对应midlet.menuListHighmidlet.menuListInstru//按照逻辑不可能出现这种情况4高分屏幕HighScoreScreen类的实现最高得分屏幕用来显示当前最高得分(到目前为止的最好成绩)第33页共42页HighScoreScreen类是Form的子类,并且实现了CommandListener接口,其构造函数在Form上添加了当前最好成绩的字符串组件Stringltem以及添加了返回菜单的软键。HighScoreScreen(escapeeMIDlet{super("最好成绩");//实现父类的构造函数,指定Form的名称longbestTime=midlet.getBestTime();//从midlet中获取最好成绩floatBestTime_Second=(float)bestTime/1000;//将成绩转化为以秒为单位(原来是毫秒)Stringtext=(bestTime==-1)?"目前还没有,期待您的表现哦!"//判断是否存在这个成绩当玩家按下返回软键后,将回调midlet类的highScoreBack,显示游戏菜单。{}5.子弹Bullets类的实现(1)构造函数由于Bullets类继承了Sprite类,因此在Bullets的构造函数中必须实现Sprite类的构造函数,也就是调用super语句。构造函数还用来获取必要参数例如帧的宽度和高度,以及定位精灵的参考点等简单的操作。构造函数的代码如下:defineReferencePixel(frameWirandom-newRandom);(2)设置参数为了让Bullets类更加面向对象,这里还定义了两个public方法,外部类可以调用这两个方法来设置子弹的数目,以及画布的宽度和高度,这两个方法非常简单。这两个方法代this.BULLETS_NUM=BU}this.CanvasWidth=Cathis.CanvasHeight=Can}下面的代码将初始化一个子弹的所有初始属性:bullets[i][0]=(random.nextInt()&0x7ffffff)%4;//采用随机值取子弹的类型,范围为[0,3](包含端点)caseBULLET_TYPE_LEFT://子弹类型为从屏幕左方飞入bullets[i][1]=-frameWidth;//子弹的x坐标为较小的负数(屏幕左边)bullets[i][2]=(random.nextInt()&0x7ffffff)%CanvasHeight;/随机取子弹的y坐标(0~bullets[i][3]=(random.nextInt()&0x7ffff)%3+1;//随机取子弹x方向的速度,范围为第34页共42页bullets[i][4]=(random.nextInt()%3;//随机取子弹y方向的速度,范围为[-2,2]bullets[i][1]=CanvasWidth+frameWidth;//子弹的x坐标为略大于屏幕宽度的正数(屏幕右bullets[i][2]=(randobullets[i][3]=((random.nextInt()&0x7ffffff)%3+1//随机取子弹x方向的速度,范围为[-3,-1]之间bullets[i][4]=(random.nextInt())%3;//随机取子弹y方向的速度,范围为[-2,2]bullets[i][1]=(random.nextInt()&0x7ffffff)%Canva//随机取子弹的x坐标为[0,CanvasWidth]之间的正数坐标为一个较小的负数(处于屏幕上方)bullets[i][3]=(random.nextInt())%3;//随机取子弹x方向上的速度范围为[-2,2]之间bullets[i][1]=(random.nextInt()&0x7ffffff)%Canva//随机取子弹的x坐标为[0,CanvasWidth]之间的正数bullets[i][2]=CanvasHeight+frame//子弹的y坐标为一个略大于屏幕高度的正数数(处于屏幕下方)bullets[i][3]=(random.nextInt()%3;//随机取子弹x方向上的速度范围为[-2,2]之间bullets[i][4]=((random.nextInt()&0x7fffffff)%3+1//随机取子弹y方向的速度,范围为[-3,-1]之间}使用上面的方法可以随机设置子弹的位置和速度,使得这些子弹具有一点人工智能的色彩,但是有些情况下,某个方向的速度会出现0的情况,也就是子弹沿着x方向或者y方向移动,影响了子弹随机运动的视觉效果,为了避免这种情况的发生,将检测子弹某方向速度出现0的情况,并且给该方向设置一个默认速度,修正子弹运行轨迹的代码如下:if(bullets[i][3]==0)//如果子弹的x方向{if(bullets[i][0]=BULLET_TYPE_RIGHT|bullets[i][bullets[i][3]=-DEFAULT_SPEED;//根据子弹类型设置x方向上}if(bullets[i][4]==0)//如果子弹的y方向上的速度为0{if(bullets[i][0]=BULLET_TYPE_RIGHT|bullets[i][bullets[i][4]=-DEFAULT_SPEED;//根据子弹类型设置y方向上速度为默认值elsebullets[i][4]=DEFAULT_SPEED;}上面已经初始化了一颗子弹的属性,对于屏幕上的多个(数目为BULLETS_NUM)子弹,可以使用遍历数组的方法来一一设定:}第35页共42页子弹运动的代码如下:privatevoidtick(inti){bullets[i][1]+=bullets[i][3];//x方向上根据初始位置和速度进行移动bullets[i][2]+=bullets[i][4];/y方向上根据初始位置和速度进行移动if(bullets[i][1]<-5||bullets[i][1]>CanvasWidth+5){//当超出屏幕的左右边界时bullets[i][3]*=-1;//x方向的速度取反}if(bullets[i][2]<-5||bullets[i][2]>CanvasHeight+5){//当超出屏幕的上下边界时bullets[i][4]*=-1;//y方向的速度取反和子弹的初始化一样,上面的代码完成了第i颗子弹的运动,想要所有的子弹运动起来,只要遍历子弹数组,对所有子弹做相同处理即可:tick(i);//遍历子弹数组,移动所有子弹}(5)子弹的绘制绘制所有子弹的代码如下:for(inti=0;i<bullets.length;i++){//遍历子弹数组,绘制每颗子弹if(bullets[i][5]!=ALIVE){//如果子弹处于非激活状态,则跳过}draw(g,i);//绘制第i颗子弹(6)碰撞检测在游戏的运行中,始终要检测子弹和逃亡飞机是否发生碰撞,这里使用Sprite类的collidesWith方法来检测精灵与精灵之间的碰撞。飞机为不规则形体,因此这里使用的是象素级碰撞检测。if(bullets[i][5]!=ALIVE){//如果子弹处于非激活状态则进行下一轮循环}setPosition(bullets[i][1],bullets[i][2]);//将子弹设置到子弹数组所指定位置returnfalse;//如果未发生碰撞,则返回falsef6.逃亡飞机Escapee类的实现(1)定义变量下面将用代码实现飞机的基本功能,在此之前先定义以下一些变量或者常量:第36页共42页privateintCanvasWidth,CanvasHeight;//画布的宽度和高度(2)初始化飞机的初始化分为几个小方法,需要初始化的内容为游戏帧的宽度和高度、画布的宽度和高度、定义参考点、设置生命(是否存活)以及设置初始帧publicEscapee(Imageimage,intframeWidth,intframeHeight)super(image,frameWidth,frameHeight);//实现Sprite精灵类的构造函数一0this.CanvasHeight=CanvasHeight;//获得屏幕的高度}于飞机是否存活提供了两个方法供外部设置和查询:}(4)飞机移动move(0,-SPEED);//调用move方法向上移动坐标,每次移动幅度为SPEED个象素if(getY(<0)setPosition(getX(),0);//如果到达上边界(y坐标为0)则停止不动move(0,SPEED);//调用move方法向下移动坐标,每次移动幅度为SPEED个象素//如果到达下边界(y坐标靠近CanvasHeight)则停止不动if(getY()>CanvasHeight-frameHeight)setPosition(getX(),Canv}if(direction==LEFT{//如果方向向左第37页共42页//如果到达左边界(x坐标靠近0)则停止不动move(SPEED,0);//调用move方法向右移动坐标,每次移动幅度为SPEED个象素//如果到达右边界(x坐标靠近CanvasWidth)则停止不动if(getXO>CanvasWidth-frameWidth)setPosition(CanvasWi}(5)帧的设置if(!isMove)setFrame(O);//设置游戏帧为0}7.游戏画布escapeeCanvas类的实现(1)游戏变量staticfinalintUP=0;//代表玩家按下了游戏上键staticfinalintLEFT=1;//代表玩家按下了游戏左键staticfinalintDOWN=2;//代表玩家按下了游戏下键staticfinalintRIGHT=3;//代表玩家按下了游戏右键privateTiledLayerbackground;//TiledLayer类对象,代表游戏背景privateEscapeeescapee;//Escapee类的对象privateintCanvasWidth=gprivateImageimage;//Image对象,用来加载图片资源privatestaticfinalintMILLIS_PER_TICK=50;//每个tick的毫秒时间privatebooleanisprivatebooleanisCollidesWith=false;//是否玩家飞机和子弹碰撞privatelonggameDuration=0;//游戏的持续时间privatevolatileThreadanimationThread=null;/游戏线程(2)构造函数escapeeCanvas(escape{super(true);//抑制非游戏键盘}(3)加载游戏资源毕业设计(论文)第38页共42页intbackColumns=CanvasWidth/image.getWidth()+1;//计算地图数组的列数intbackRows=CanvasHeight/image.getHeight()+1;/计算地图数组的行数backgroundnewTiledLayer(backColumns,backRows,image,image.getWidth(for(inti=0;i<backColumns*bac{background.setCell(x,y,1);//填充地图数组,这里只有一张图片}飞机类Escapee

温馨提示

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

评论

0/150

提交评论