2024年1月23日发(作者:汉阳煦)
【精品】:国内外手机游戏的研究现状
武汉科技大学中南分校毕业设计(论文)
目录
第一章 引言 ............................................... 1
1.1 国内外手机游戏的研究现状 ..................................................... 1
1.2 手机游戏的技术分类 ................................................................. 1
1.3 研究意义 .................................................................................... 2 第二章 基于J2ME的手机游戏开发平台概述 ................... 4
2.1 什么是J2ME ............................................................................... 4
2.2 J2ME 平台体系结构 ................................................................... 4
2.3
KVM ............................................................................................ 5
2.4
6
2.5移动信息设备描述(MIDP) .......................................................... 8
2.6MIDP 应用程序 ............................................................................ 8
2.7 MIDP UI 组件 ............................................................................. 9 第三章手机游戏开发的相关知识及工具 ...................... 12
3.1 手机游戏的画面 ........................................................................ 12
3.2手机游戏中的按键 ....................................................................
13
3.3线程使用.................................................................................... 14
3.4 手机硬件平台特点 ....................................................................
14
3.5 手机游戏开发工具软件 ............................................................ 15 第四章 手机游戏一“逃亡者”的设计与实现 ................. 17
4.1游戏描述.................................................................................... 17
4.2可行性研究 ................................................................................ 17
4.3游戏设计.................................................................................... 17
4.4详细编码设计 ............................................................................ 19
4.5程序打包、下载安装与运行 .................................................... 19
4.6 最后效果图 ............................................................................... 20 第五章 结束语 ............................................
21 参考文献 ................................................. 22 致
谢 ................................................. 23 附录 ..................................................... 24
第 1 页 共 42 页
杨永:基于J2ME的手机游戏设计
第一章 引言
1.1 国内外手机游戏的研究现状
近年来,因特网在国内迅速普及,导致了网络游戏的高速发展。同样手机的普及,导致了手机游戏市场呈现爆炸式的发展。尤其是国内外巨大的手机拥有量,更是让商家看到了商机,手机游戏市场利润将会十分丰厚。面对潜力如此巨大的手机游戏市场,各游戏开发商、运营商、服务商以及手机终端厂商等都纷纷开始了各自的应战准备,以便抢占商机。
诺基亚、索爱、摩托罗拉等各大手机厂商开始不断的提升手机在游戏方面的性能,同时还在手机操作系统方面采用开放式的平台,方便用户享受不同的
[1]手机游戏业务。而国内游戏开发商,如盛大、网易等公司,纷纷跻身手机游戏开发商行列。新浪、搜狐等著名的门户网站,也纷纷涉足手机游戏领域,相继开辟了各自的手机游戏频道和栏目,其他一些游戏网站也都全面加快了手机游戏开发的步伐。目前SUN公司的J2ME CLDC/MIDP环境和高通公司的BREW(Binary
Runtime Environment for Wireless)客户端程序是国内外游戏开发的两大主要平台。中国电信业巨头中国移动建立了无线Java增值服务体系,推出了基于SUN公司的J2ME 环境的“百宝箱”业务,包括游戏类、商务类、生活类等丰富的数据服务。中国移动用户只要使用支持Java的手机,通过GPRS的无线上网方式,访问移动梦网门户的“百宝箱”服务菜单,就能方便地下载各种由Java语言编写的应用程序。而中国联通与高通公司合作,采用高通公司的BREW平台技术,推出了“神奇宝典”业务,中国联通用户可以从联通公司的应用下载服务器上以无线方式下载应用程序。
1.2 手机游戏的技术分类
手机游戏按实现的技术分,可分为嵌入式游戏、浏览器游戏、基于J2ME和其它的解释语言的游戏、基于C++应用程序和其它编译语言的游戏等。
1. 嵌入式游戏
嵌入式游戏在出厂时就固化在手机的芯片中,像Nokia的“贪吃蛇”就是一个经典的例子。这些游戏是为手机量身定做,能够充分发挥特定手机的强大性能,从而达到其他类型的游戏所无法达到的效果,而且嵌入式游戏在运行过程中不会让用户产生费用。但是这些游戏是依据手机生产厂商的平台进行开发
[1] J2ME开发网?J2ME中文教程?PDF电子文档 ,2005-9-5
第 1 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
的,出厂时设置了几款游戏,玩家就只能在这几款游戏当中进行选择,而不能根据用户自己的喜好对游戏进行升级、删除等操作,所以嵌入式游戏的缺点也是明显的,无法给玩家带来新鲜感,玩家容易对固定的几款游戏产生厌倦。
2. 浏览器游戏
WAP是一种用手机上网的网络服务。进行WAP游戏时,通过手机自带的WAP浏览器来浏览手机网站上的页面,并通过页面中描述的内容来进行游戏。形式上类似于网上常见的一些心理测验之类的交互手段。WAP游戏没有图片和容量的限制,但这类游戏大多采用文字交互方式,这样游戏性就不强,缺乏直观感觉。而且在收费上,WAP游戏费用比较高,因为在游戏的过程中,您不仅需要向服务商交纳一定的费用,而且同时要向中国移动或中国联通交纳一定的流量费用。
. 基于C++应用程序和其它编译语言的游戏 3
使用C++应用程序和其它编译语言开发游戏也是一种较好的开发方式。编译语言程序能提供更好的控制用户界面,而且编写的应用程序相比用脚本语言编写的程序,效率更高、使用的内存更少,并且执行得更快。但由于这些编译语言往往不具有跨平台性,而且由于编译语言的特点,往往需要较长的开发周期。
4. 基于J2ME和其它解释语言的游戏
Java 2 Micro Edition (J2ME)是一种针对移动电话和PDA等小型设备的Java语言。采用J2ME极大的提高了手机支持游戏的能力。它有比WAP游戏更易控制的界面,J2ME游戏摆脱了纯文字交互的方式,它允许使用图形动画,并且可以通过无线网络连接到远程服务器。而且Java是面向对象程序设计的语言,它最大的特点是一次编写、到处运行,即平台无关性。现在支持Java的手机比较普及,它也已经成为目前比较好的移动游戏开发环境。
1.3 研究意义
对手机功能的扩充。
手机游戏成了电信增值业务中一项主要的应用,在公交车等公共场合不时会看到拿着手机玩游戏的人。相比较早开发的“贪吃蛇”、“俄罗斯方块”等手机游戏,如今的手机游戏,无论是从视觉效果、听觉效果还是游戏的可玩性来说,都要精彩的多。在全球,移动电话数量巨大,除美国之外,其他各个发达国家拥有手机的人数比拥有计算机的人数还多。在我国,手机拥有量甚至超过了美国的人口数量,而且每个月手机数量还正以惊人的速度递增着。手机市场的高速增加带动了手机游戏市场的急速膨胀,基于JAVA、BREW等技术平台
第 2 页 共 42 页
杨永:基于J2ME的手机游戏设计
[2]的手机游戏市场规模纷纷呈现几何增长态势。
[2] 林邦杰?Java程序设计入门教程?中国青年出版社,2001-9-15 第 3 页 共
42 页
武汉科技大学中南分校毕业设计(论文)
第二章 基于J2ME的手机游戏开发平台概述 2.1 什么是J2ME
J2ME 是SUN 公司针对嵌入式、消费类电子产品推出的开发平台,与J2SE 和J2EE 共同组成Java 技术的三个重要的分支。J2ME 实际上是一系列规范的集合,
由JCP 组织制定相关的Java Specification Request(JSR)并发布,各个厂商会按照规范在自己的产品上进行实现,但是必须要通过TCK 测试,这样确保
[3]兼容性。
2.2 J2ME 平台体系结构
J2ME 平台是由配置(Configuration)和简表(Profile)构成的。配置是提供给最大范围设备使用的最小类库集合,在配置中同时包含Java 虚拟机。简表是针对一系列设备提供的开发包集合。在J2ME 中还有一个重要的概念是可选包(Optional -Package),它是针对特定设备提供的类库,比如某些设备是支持蓝牙的,针对此功能J2ME 中制定了JSR82(Bluetooth API)提供了对蓝牙的支持。目前,J2ME 中有两个最主要的配置,分别是Connected Limited Devices
Configuration(CLDC)和Connected Devices Configuration(CDC)。他们是根
[4]据设备的硬件性能进行区分的。
CDC 的硬件参数:
(1) 2M 以上内存。
(2) 具有网络连接能力,通常为无线网络。
(3) 需要实现java 虚拟机规范的全部功能。
(4) 32 位或者64 位的处理器。
CLDC 的硬件参数:
(1) 512 KB 以下内存
(2) 有限能源供应(通常使用电池)。
(3) 有限或非持续网络连接。
(4) 简单的用户界面。
(5) 16 位或者32 位的处理器。
[3][4] 黄聪明?JAVA移动通信程序设计J2ME MIDP?清华大学出版社
第 4 页 共 42 页
杨永:基于J2ME的手机游戏设计
从上述的标准中我们不难看出CLDC 主要针对那些资源非常受限的设备比如手机、PDA、双工寻呼机等。而CDC 主要面对那些家电产品,比如机顶盒、汽车导航系统等。简表是以配置为基础的,例如Mobile Information Devices Profile
(MIDP)就是CLDC 上层的重要简表。与配置的纵向特性不同的是,简表是横向的。
-1是J2ME 体系结构的框图: 下图2
The J2ME Environment
J2ME Appliacation Layer
MIDLet
MIDLet Class Layer
MIDLet Application Manager
图2-1J2ME 体系结构框图
(1) 主机操作系统层(Host Operating System Layer):这一层为特定硬件设备的操作系统层。
(2) Java虚拟机层(Java Virtual Machine Layer):这一层是Java虚拟机的一个实现,它是为特定为特定设备的主机操作系统定制的,支持一个特定的J2ME配置。
(3) 配置层(Configuration Layer):配置层定义Java虚拟机的功能和特定类别设备上可用的Java类库的最小集。从某种程度上说,一个配置定义了Java平台的功能部件和库的共同性,开发者可以假设这些功能部件和库在属于某一特定类别的所有设备上都是可用的。这一层对用户是透明的,但它对描述的实现者非常重要。
(4) 描述层(Profile Laver):描述层定义了特定类别设备上可用的应用程序编程设备的主机操作系统定制的,支持一个特定的J2ME配置。
在手机上,KVM, CLDC, MIDP分别实现了J2ME体系结构中的Java虚拟机层、配置层和描述层。
2.3 KVM
CLDC 和 MIDP都是运行在Sun公司的KVM上。KVM是一个专门为小型、资源受限设备所设计的紧凑的、便携的Java虚拟机。Java虚拟机是Java程序语言的核心,只要Java程序在执行,Java虚拟机也必定在执行。Java虚拟机是实际执行Java程序的引擎,也是Java语言具有这么多优良特色的关键所在。当你执行Java程序时,程序内的指令其实并不是由硬件直接执行,而是由一个特别的软第 5 页
共 42 页
武汉科技大学中南分校毕业设计(论文)
件一一读取这些指令来执行的。简单地说,Java程序不是被底层的CPU直接执行,而是被“虚拟CPU”执行的,所谓的虚拟CPU其实就是计算机上执行的一个特别软件。虚拟机的优点甚多,比如移植方便,只需要移植虚拟机和相关的支持程序库到新的硬件架构上,所有上层的应用程序都不需要更动就完成移植了。虚拟机的另一个好处是它在计算机软硬件间加入一抽象层来分离和保护,
[5]可以防止恶作剧的程序暗中搞鬼。
2.4 CLDC
2000 年5 月,Java Community Process(JCP)公布了CLDC1.0 规范(即JSR30)。作为第一个面对小型设备的Java应用开发规范,CLDC是由包括Nokia,Motorola和Siemens在内的18 家全球知名公司共同协商完成的。CLDC是J2ME核心配置中的一个,可以支持一个或多个profile。其目标主要面向小型的、网络连
接速度慢、能源有限(主要是电池供电)且资源有限的设备,如手机、机顶盒、PDA
等。
CLDC 的核心是虚拟机和核心类库。虚拟机运行在目标操作系统之上,对下层的硬件提供必要的兼容和支持;核心类库提供操作系统所需的最小的软件需求。
1核心类
2库虚拟机
可选包
Profile
配置
操作系统
图2-2 CLDC 标准构架
2.4.1 CLDC 的目标
(1) 为小型的、资源受限的连接设备定义一个Java 平台标准。
(2) 允许向上述设备动态的传递Java 应用和内容。
(3) 使Java 开发人员能够轻松的在这些设备上进行应用开发。 2.4.2 CLDC
的整体需求
(1) 能运行在绝大多数的小型的、资源受限的连接设备上。
(2) 用CLDC 为上述设备开发的应用尽可能的不使用设备的本地系统软件。
[5] 卢军?J2ME应用程序开发手机、PDA程序开发捷径?中国铁道出版社
第 6 页 共 42 页
杨永:基于J2ME的手机游戏设计
(3) 定义能应用在绝大多数上述设备上的最小子集的规范。
(4) 保证在不同类型上述设备之间代码级的可移植性和互操作性。 2.4.3
CLDC 的硬件需求
由于CLDC 要面向尽可能多的设备,而这些设备所使用的硬件又各不相同。因此CLDC 规范中并没有指明需要某种硬件支持,只是对设备的最小内存进行了限制。CLDC 规范中要求硬件必须达到以下要求:
(1) 至少160KB 的固定内存以供虚拟机和CLDC 核心类库使用。
(2) 至少32KB 的动态内存以供虚拟机运行时使用(堆栈等)。
这里所说的固定内存是指拥有写保护,不会因关机而抹去的ROM。对于具体的设备的具体实现,这些需求也可能有变化。这里所规定的160KB 是CLDC 规范中的要求,实际也可以是128KB 左右。
2.4.4 CLDC 的软件需求
和硬件类似,CLDC 上运行的软件也是多种多样的。例如,有些设备支持多进程操作系统或者支持文件系统;而有些功能极其有限的设备并不需要文件系统。对于这些不确定性,CLDC只定义了软件所必须的最小集合。CLDC 规范中要求操作系统不需要支持多进程或是分址空间。
2.4.5 CLDC 的功能范围
在CLDC1.0 版本中定义了以下功能:
(1) Java 核心语言与Java 虚拟机的特性
(2) 核心Java 类库
(3) 输入/输出
(4) 对网络的支持
(5) 对安全性的支持
(6) 对国际化的支持
2.4.6 CLDC特征
(1) 安全
(2) 遵守Java语言规范
(3) 遵守Java虚拟机规范
(4) 要求类文件验证
J2EE和J2SE为桌面计算机和服务器的企业级应用和开发提供了非常丰富的库函数。不幸的是这些库需要几十兆的内存来运行,因此并不适合于资源受限的小型设备。所以CLDC针对小型受限设备重新制定了一个类库。为了保证应用程序的兼容性和可移植性,包括进CLDC的大多数类库都是J2SE中规定的子集,其它一些是由CLDC规定的专用于移动设备的类。包括:从J2SE中继承的第 7 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
[6]类、国际化支持类、系统属性类、CLDC专用类四个方面。 2.5移动信息设备描述(MIDP)
J2ME提供了描述的概念,使得可以为特定的设备家族定义相同的Java平台。描述可以满足两种明显不同的可移植性需求:
(1)描述为在一个特定的设备家族实现应用提供了完整的工具,比如传呼机、机顶盒、移动电话、洗衣机或智能玩具。
(2)可以创建一种描述来支持重要的、一致的一组应用,这些应用可能会在几各不同的设备上运行。
简单地说,描述就是应用和市场的设备家族之间的协议。处于同一个设备家族中的所有设备都必须实现其描述所定义的特征,并且要求应用只使用这个特定描述所提供的功能。在实现层次上,描述被简单地定义为应用在特定配置上的Java
API和类库的集合,同时为市场中特定的设备家族提供了附加的面向
[7]特定领域的功能。
现在,己经有了五个规范化了的描述,如表2-1
表2-1 五个规范化描述
描述名称 下层配置
Mobile information device profile(MIDP) CLDC
Personal digital assistant profile CLDC
Foundation profile CDC
Personal profile CDC
RMI profile CDC
2.6MIDP 应用程序
CLDC和MIDP组合起来为创建移动电话应用程序提供了完整的环境。MIDP应用程序或者称为MIDlet. 其模型如图2-3所示
[6] JSR-000139 Connected Limited Device Configuration 1.1 [7]
第 8 页 共 42 页
杨永:基于J2ME的手机游戏设计
The J2ME Environment
J2ME Appliacation Layer
MIDLet
MIDLet Class Layer
MIDLet Application Manager
图2-3MIDlet应用框
MIDlet 有三个状态,分别是pause、active 和destroyed。在启动一个MIDlet的时候,应用管理软件会首先创建一个MIDlet 实例并使得他处于pause
状态,
active 状态,也就是所说的运行状当startApp()方法被调用的时候MIDlet
进入
态。在active 状态调用destroyApp(booleanunconditional)或者pauseApp()方法可以使得MIDlet 进入destroyed 或者pause 状态。值得一提的是destroyApp(boolean
unconditional)方法,事实上,当destroyApp()方法被调用的时候,AMS 通知MIDlet 进入destroyed 状态。在destroyed 状态的MIDlet 必须释放了所有的资源,并且保存了数据。如果unconditional 为false的时候, MIDlet 可以在接到通知后抛出MIDletStateChangeException 而保持在当前状态,如果设置为true
的话,则必须立即进入destroyed状态。下图2-4说明了MIDlet 状态改变情况:
Start
startApp
Active Paused
pauseApp
destroyApp destroyApp
Destroyed
图2-4 MIDlet 状态图
2.7 MIDP UI 组件
In 组件与低级绘制相比,用在游戏开发上的机会较少,但还是会到。所谓UI组件,是指继承了类的
,,x,j
avam 等。
下图为我们展示了整个LCDUI 包的体系:
第 9 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
Display CommandLister
Ticker Displayable Command
Canvas Screen
Image
Graphics
Font
图2-5 LCDUI包的体系
Screen 类属于高级图形用户界面组件, Canvas 是低级图形用户界面组件,在同一时刻,只能有唯一一个Screen 或者Canvas 类的子类显示在屏幕上,我们可以调用Display 的set Current()的方法来将前一个画面替换掉,我们必须自行将前一个画面的状态保留起来,并自己控制整个程序画面的切换。同时我们可以运用d 类来给我们的提供菜单项目的功能,分别是:mmand、Command. CANCEL、、、、Comm 、 和,我们在Display
able对象中定义了add Command()和remove Command()两个方法,这就意味着我们可以在高级UI 和低级UI 中同时使用Command 类,同时我们通过注册Command
事件来达到事件处理的目的,即Command 必须与Command Listener 接口配合使用才能反映用户的动作。
与高级UI 相比,低级UI 就自由很多,任何时候我们可以调用repaint()产生重绘事件,调用完了repaint()会立刻返回,调用paint()回调函数则是由另一个专门的线程来完成。底层事件大致可分为三类:Press Events(按键事件),Action
Keys(动作按键,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
第 10 页 共 42 页
杨永:基于J2ME的手机游戏设计
中定义了一系列的动作事件:UP,DOWN,LEFT,RIGHT,GAME_A,GAME_B,GAME_C,GAME_D,当按下这些按键时会映射到我们自己为每个按键事件编写的方法,来完成一些动作。不过我们在MIDP2.0 里我们已经有专门的游戏开发包了,所以我在这里就不重点介绍了。
触控事件主要面向高端设备, 并非JTWI 要求强制支持的,其核心方法为:pointerPressed(),pointerReleased(),pointerDragged(),分别对应我们通常所用的移动设备手写笔的点,击,拖拽几个动作,我们在这三个方法里可以定义相应的事件处理函数。在索爱P910C 这样的高端手机上,支持屏幕的触控事件,我们在屏幕上点击,可以引发pointerPressed()函数,并传入当时位置的坐标,放开后,会引发pointerReleased()函数,同样也会传入坐标,具体的使用方法和keyPressed()以及keyReleased()大同小异。
第 11 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
第三章手机游戏开发的相关知识及工具 3.1 手机游戏的画面
MIDlet 类本身并没有提供直接操作画面显示的功能,因此在MIDlet类的子类中也没有直接操作画面显示的功能。因此,我们要使用提供了管理画面显示功能的y类。这个Display类可以y类的子类显示在画面上。
Displayable类的子类大致说来可以分为两种,分别为用来进行线与图形,图像的低级描绘类,与用于显示警告与文本的输入,选择列表等UI组件类。前者是类后者是dition.
类与其子类(Alert,FomList,TextBox类等)之旬的关系。
它们之旬的关系如下图3-1:
Object
Object
Display
Canvas Screen
TextBox Form List Alert
图3-1 画面显示类图
用来显示画面用的Display对象,可以从Display类的Static方法Display#getDisplay(MIDlet) 值获取。通过在获取的Display对象,就可以让Displayable对象显示在画面上。
MIDP中可以使用的图像格式为PNG格式。要获取图像,必须使用类的Static方法。Image类的Static方法,提供了从byte数据中提取Image对象,以及指定与MIDlet相同JAP文件的路径后获取对象的功能。创建Image对象的Static方法:
第 12 页 共 42 页
杨永:基于J2ME的手机游戏设计
(1)Image#createImage(byte[]imageData,int imageOffset,int imageLengt)
(2)Image#createImage(int souce) (3)Image#createImage(int width,int
height)
(4)Image#createImage(String name)
为了减少额外错误处理,在调用出来的时候要进行try-catch或throw。下面的代码展示了如何创建Image对象:
Image img;
Try{
img=Image(“/”)
}catch(ption e){
}
上一章提到了MIDP UI 的组件,这里不在做解释。Form类 是能够将一个以上的图像文本,Item类的子类(ChoiceGroup,DataField,Gauge,ImageItem)混合显示的组件。List类,与PC的UT组件中的List组件一样,是用来显示项目的列表,以让用户来进行选择为目的的组件。也可以是附有选择按钮的列表与附有复选框的列表。文 本 框 是一个允许用户进行编辑的文本区域。一个文本框有一个足以容纳的最大字符数量,具体的大小依赖于不同M工DP的实现或者是移动电话的存储器大小。在文本框中字符显示的顺序和格式由设备决定。当文本框中的字符数量大于一次被显示的字符数量时用户可以通过滚动来编辑一个文本框中的部分字符。Alert ,Form,List,TextBox各类的超类Screen由于与Canvas类一样,是继承了Displayable类,因此可以用Display # setCurrent
(Displayable)方法来将其显示在画面上。
3.2手机游戏中的按键
在MIDP中,每一个按键事件将产生一个按键代码。在MIDP的Canvas类中定义的按键代码如下所示:KEY_NUM0,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规范的移动设备上运行。
在Canvas类中,定义了一些通用按键值,游戏按键中的UP、DOWN、LEFT、RIGHT、FIRE、GAME_A、GAME_B,在MIDlet运行时,这些按键的
[8][9]按键值可以通过getKeyCode()方法确定。
[8] 洪维恩?Java 2面向对象程序设计?中国铁道出版社
第 13 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
3.3线程使用
我们所创建的动画,是使用线程把所准备的多张图像按顺序描绘出来。所谓的线程就是指程序的运行单位,使用线程可以同时进行处理。
在这里,为了要做出线程,我们会用到le接口。同样的处理虽然也可以用到类与类来进行,不过它们都需要创建出继承各类的另一个类,所以还不如使用Runnable接口。
将Runnable接口作为实现的类,必须将Runnable接口的run()方法重新定义。
在这个run()方法中,将要编写以线程所处理的内容。下面的代码为在run()方法内调用Canvas#repaint()方法来进行再描绘的范例。
Import .*
Class ThreadTest extends canvas implements Runnable{
Public void run( ){
Repaint( );
}
Protected void paint(Graphics g){
}
}
只在以Runnable接口为实现的类中再定义run() 方法,是不能让线程运行的。要运行的时候必须使用到Thread类。要调用Thread类的Constructor中指定Runnable接口参数的constructor,来产生Thread对象。接下来,要用产生的Thread接口来调用Thread # run() 方法来启用线程。
线程类由于会在Thread#start()方法被调用出来后调用Runnable#run( )方法,因此编写在run()方法中的处理将会被自动运行。线程的终止一般可通过两种方法实现;自然撤消或是被停止。自然撤消是指从线程的run()方法正常退出。
通 常,当一个应用程序停止运行,例如用户从一个主页切换到另一个主页
[10]时,它就会调用stop()方法来终止原主页中正在运行的所有线程。 3.4
手机硬件平台特点
手机作为一种资源有限的设备,和PC机相比,有以下一些特点: (1)处理器运算速度慢,远低于PC机的CPU运行速度。
(2)存储器容量小、存取速度慢。
[9] 焦祝军、张威?J2ME无线通信技术应用开发?北京希望电子出版社 [10] 范丹?J2ME在I-mode手机上的应用?现代计算机,2003年第7期
第 14 页 共 42 页
杨永:基于J2ME的手机游戏设计
(3)网络能力有限、带宽窄,并且因为手机的移动,容易导致手机网络地址的变化。
(4)输入/输出的多样性:手机不可能有PC机标准键盘那么多按键,也没有鼠标。它的显示能力也非常有限,譬如显示尺寸小、分辨率低等。 (5)手机由电池提供能源,会因为电池耗尽或接触不良造成经常断电。在编写
[14]手机应用程序时,必须对以上几个方面分别进行考虑。
3.5 手机游戏开发工具软件
J2ME Wireless Toolkit(J2MEWTK)是Sun公司所发布的官方版MIDP应用程序开发工具,它为编写和测试M工DP应用程序提供了一个完整的开发环境。J2ME
Wireless Toolkit()是制作手机用JAVA所必需的开发配套元件。
安装 J2MEWTK之前,一定要先安装Java2 SDK 1.3以上的版本。如果没有安装Java 2 SDK的话,J2MEWTK即使安装完成,也无法进行M工Dlet的开发工作。J2MEWTK提供菜单或按钮方式的命令。J2MEWTK中有相应的编译(集成了预验步骤)、打包、模拟运行的菜单(或按钮),以及其它辅助工具。J2SE SDK()是制作所有JAVA所必需的开发配套元件。
[11]这里介绍一下Java2 SDK及J2ME Wireless Toolkit的安装。
我们来安装制作JAVA所必需的开发配套元件J2SE SDK。先打开。
点击网页中的[Download J2SE SDK]链接,会出现了一个许可协议。仔细阅读完协议后,选中[Accept]然后再点击[Continue]。
这是选择安装程序的画面。因为你的PC的OS是WINDOWS,所以你可以试着点击[Windows Installation, Multi-language],来下载安装程序。
启动安装程序后,会出现一个许可协议的画面。看完后选同意,然后点击[Next]。
接下来,选择要安装的程序和安装到的地址。这里安装的程序就用默认的程序,安装地址也用默认的[c:j2sdk1.4.2_05]。
设定数据库文件夹,这里我们也用默认的设置。点击[Next],便开始安装了。
用安装软件安装完毕后,就要开始设定JAVA使用的环境。用鼠标右键点击桌面上“我的电脑”图标,在显示选单中选择“属性”。
打开“系统属性”,选择上面选单的“高级”,点击“环境变量”按钮,出现环
[14] 赵海廷?java语言程序设计?2005-8-8 [11] 佚名?JAVA教程
第 15 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
境变量设定窗口。
在“用户变量”和“系统变量”的表里如果没有“Path”变量,就点击“新建”。
在“变量名”一栏输入“Path”,“变量值”栏里输入刚才安装的 J2SE SDK的文件夹里“bin”文件夹的路径。这里设定为[c:j2sdk1.4.2_05bin]。输完后点击“确定”键。
下面就让我们来安装手机Java开发元件J2ME Wireless Toolkit。打开,点击网页下部的[Download]按键。
看完后选择[Accept],然后点击[Continue]。于是显示安装程序选择画面,点击[Windows Platform]的安装程序,并下载。
出现Wireless Toolkit的安装画面。选择[Next]。
下面是许可协议的画面,看完后选择[Yes]。
设定正在安装的J2SDK的路径。这里点击刚才安装J2SE SDK的[Browse..]键,设定[c:j2sdk1.4.2_05],设定完后,点击[Next]。
接下来设定安装WirelessToolkit的文件夹。这里使用预设的[c:WTK104],点击[Next]。
在程序文件夹进行注册,这里使用预设的[J2ME Wireless
Toolkit1.0.4_01],然后点击[Next]。
然后是设定的确认画面。若确认正确,点击[Next]。
安装完毕后点击[Finish]键,结束安装。
下面说明一下J2ME手机游戏开发环境:
Java手机游戏的真实运行环境是Java手机。一般来说,Java游戏的开发是先在PC机上模拟,模拟成功后再打包下载到手机上。本文的模拟环境是:
(1)系统环境Windows 2000
(2)平台支持J2SDK-1.4
(3)开发工具:采用MOTO-J2ME-SDK-5.2.1模拟器。
第 16 页 共 42 页
杨永:基于J2ME的手机游戏设计
第四章 手机游戏一“逃亡者”的设计与实现 4.1游戏描述
“逃亡者”是一款选取了一款PC 小游戏作为范例移植到手机上,它的中文名为《是男人就撑过30 秒》,虽然看似简单,但绝对有挑战性~这是总结了无数日本纵版飞行射击游戏中的武器而研究出的特殊训练软件,专门用来训练“战斗机”飞行员。在漆黑一片的宇宙中,停着一架小飞船,突然四面八方出现很多黄色的小点向小飞船聚集过来,小飞船凭借速度优势和飞行技术从黄点之间的夹缝中飞过,之后又落入新的包围圈中,直至被黄点击毁。坚持的时间越长,就说明水平越高。持续不同的时间会得到不同的评价。如图4-1 所示是它原来的游戏画面。
图4-1 《特训:是男人就撑过30 秒》游戏画面 4.2可行性研究
1.技术可行性:手机 游 戏 “逃亡者”是一款较为小型的手机游戏,根据已有的手机游戏设计经验,利用J2ME来可以实现游戏的功能。根据己往的设计进度,一款小型规模的手机游戏大概有2000,3000行代码。
2.操作可行性:该款游戏在所有支持JAVA的手机上都可运行,按键简单,易
[12]于操作。
4.3游戏设计
在进入游戏之前先显示闪屏图片,当用户按下键盘或等待3 秒后,进入游戏菜单。初始情况下,游戏菜单有三个选项,它们分别是开始游戏,游戏说明和高分记录。选择开始新游戏则进入游戏,在游戏中如果按下非游戏键盘则中断游戏返回菜单,此时菜单中增加了一个继续游戏的选项,可以返回游戏也可
[12] Jason Lam、Deaboway Chou译?J2ME游戏开发(第一版)?PDF电子文档
第 17 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
以重新开始新的游戏。当游戏结束时则进入游戏结束屏
幕,屏幕上显示了玩家的成绩和等级,以及游戏的最好成绩,如果当前成绩是最好成绩,则手机震动并播放音乐庆祝成功。在菜单中选择游戏说明或者高分纪录,则进入相应的屏幕,它们都能用“后退”软键返回菜单。菜单中的退出选
[13]项用于退出程序。游戏的流程如图4-3所示。
闪屏
新游戏 退出 游戏说明
最高记录
继续游戏
非游戏
操作
游戏 游戏说明 最高记录
Back Back 游戏
结束
游戏成绩
等级
最好成绩
图4-3 游戏系统流程图
程序中一个有10 个类,其中MIDlet 主类负责各个屏幕的切换,它们是闪屏屏幕、菜单、介绍屏幕、高分屏幕、游戏屏幕,游戏结束屏幕。游戏中使用到的类为SoundEffects(音效)、Bullets(子弹)、Escapee(逃亡小飞机)。程序的类结构如图4-4 所示。
SoundEffect
s
BulletescapeeCanvas s :GameCanvas escapeeMIDlet SplashScreeSprite
n :MIDlet
:Cancas
Escapee
:Sprite
GameOverScreeHighScoreSCreeInstructionsScreen MenuList
n n :From :List
:Canvas :Form
图4-2 游戏总体类图
下面介绍游戏线程:
[13] 李振鹏 、龚剑?J2ME手机游戏开发技术详解
第 18 页 共 42 页
杨永:基于J2ME的手机游戏设计
游戏的线程主要由三个部分组成:检测键盘输入(与玩家交互),更新游戏场景(处理游戏逻辑),绘制游戏画布。基本上所有的2D 游戏都可以按照这三个模块来设计,三个模块相互联系又互相联系,按照模块的思想来实现游戏线程将更加面向对象和便于理解。如果程序运行快于预期速度会使玩家感觉到抖动,从而影响游戏效果,因此还需要检测每帧的运行时间,如果过快则等待一段时间,如果过慢则挂起当前线程允许其他线程执行。线程的模块如图4-3所示:
检测键盘输入 更新游戏场景 绘制游戏画布
绘制缓冲区到
屏幕
否
是否快于挂起当前线程 预期速度
是
挂起等待
图4-3 游戏线程模块图
4.4详细编码设计
逃亡者游戏一共实现了几个类包括用于关于游戏外部的闪屏类、菜单类、高分屏幕类、简介屏幕类、结束屏幕类,以及用于游戏本身的游戏画布类、子弹类、逃亡飞机类和声音效果类。
详情见附录。
4.5程序打包、下载安装与运行
J2ME Wireless Toolkit 能自动对 MIDlet 套件进行打包。打包产生两个文件,即一个MIDlet 描述符和一个MIDlet套件JAR。描述符是一个小文本文件,包含有关 MIDlet 套件的信息。JAR 包含组成 MIDlet 套件的类文件和资源。
第 19 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
4.6 最后效果图
图4-6游戏运行画面(一) 图4-7 游戏运行画面(二) 图4-8 游戏结束画面
第 20 页 共 42 页
杨永:基于J2ME的手机游戏设计
第五章 结束语
本文以基于J2ME平台的手机游戏的功能开发为线索,进行了相关理论研究,实验和项目开发。首先介绍了J2ME的用途和基于J2ME平台手机开发的国内外发展情况,然后研究介绍了J2ME平台的特点和手机游戏开发的关键知识点。最后以如何在J2ME环境下实现一款射击类手机游戏的开发过程做了一个详细的介绍。其主要工作为:
1.研究介绍了J2ME平台的用途和基于J2ME平台手机开发的国内外发展情况。
2.研究介绍了J2ME平台的特性和体系结构。重点介绍了MIDP类库,应用程序的体系结构,程序开发周期,工具和实例。
3.研究介绍了J2ME游戏开发的关键技术知识。
4.实现了一款射击类手机游戏一“逃亡者”,重点解决了游戏角色的表示,游戏角色及游戏流程的控制,对游戏按键事件的处理,并对整个游戏开发过程做了一个详细的介绍。
第 21 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
参考文献
[1] J2ME开发网?J2ME中文教程?PDF电子文档 ,2005-9-5
-9-15 [2] 林邦杰?Java程序设计入门教程?中国青年出版社,2001
[3] [4] 黄聪明?JAVA移动通信程序设计J2ME MIDP?清华大学出版社 [5] 卢军?J2ME应用程序开发手机、PDA程序开发捷径?中国铁道出版社 [6] JSR-000139
Connected Limited Device Configuration 1.1
[7]
[8] 洪维恩?Java 2面向对象程序设计?中国铁道出版社
[9] 焦祝军、张威?J2ME无线通信技术应用开发?北京希望电子出版社 [10] 范丹?J2ME在I-mode手机上的应用?现代计算机,2003年第7期 [11] 佚名?JAVA教程
[12] Jason Lam、Deaboway Chou译?J2ME游戏开发(第一版)?PDF电子文档
[13] 李振鹏 、龚剑?J2ME手机游戏开发技术详解
[14] 赵海廷?java语言程序设计?2005-8-8
[15] JAVA手机网[]
[16] 温尚书?J2ME无线通信实用案例教程?清华大学出版社
[17] Jason Lam, Deaboway Chou译?J2ME游戏开发(第一版)?PDF电子文档
[18] 、?程序设计教程?清华大学出版社
第 22 页 共 42 页
杨永:基于J2ME的手机游戏设计
致 谢
首先感谢我的指导老师罗奇导师,他在我的毕业设计过程中提出了指导性的方案和架构,特别是指引我阅读相关的资料和书籍,使我更能迅速学习掌握知识并完成了这个毕业设计。
感谢答辩组对本毕业设计的考核,如果可以得到各位专家的认可将对我的学习和工作给予极大的鼓励。你们客观的评价和建议我将牢记在心,在今后的发展中扬长避短,更加努力的严格要求自己。
感谢学校对我的培育,让我从思想上素质上知识上得到很大的提高,本科学习中的各科老师的悉心教导让我掌握了基本知识.
感谢我的同学在设计完成前后对我的得力帮助,没有同学的共同学习进步也许就没法完成设计,没有同学对程序的测试,也许就难以发现一些潜在的错误,在此一并表示感谢。
在此一并祝愿学校领导、老师、同学工作顺利,事业更上一层楼;同时也祝愿学校更加辉煌。
第 23 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
附录
根据详细设计对各个类进行编码实现:
1.主类escapeeMIDlet 的实现
MIDlet 被用作一个状态机来管理各种屏幕以及它们之间的转换。例如,当显示splash 屏幕时,该类和类SplashScreen(通过方法splashScreenPainted 和
splashScreenDone)共同在方法init 中完成背景初始化。而使用方法readRecordStore 和writeRecordStore 在一个名为 “BESTTIME”的记录存储区中保存最高得分。
(1)实现闪屏
游戏的最开始将会出现一幅和游戏相关的图片,它会停留一小段时间,然后才进入游戏菜单。游戏闪屏使用得当将会增加整个游戏的视觉效果,而且虽然画面在此期间停留不动,后台程序却是忙碌的,一般在此期间完成基本的初始化工作。在startApp 方法中,将游戏的显示权交给闪屏。如果中断之前的显示内容为游戏画布,则重新启动画布的线程,显示权仍然交给画布。
public void startApp()
{
Displayable current = play(this).getCurrent(); //获得关于显示的设备上下文 if (current == null)
{
play(this).setCurrent(new SplashScreen(this)); //第一次将显示闪屏 }
else
{
if (current == myCanvas)
{
(); //重新开始游戏线程
}
play(this).setCurrent(current); //显示游戏画布内容
}
}
关于闪屏实现的代码如下:
void splashScreenPainted()
{
new Thread(this).start(); //启动幕后的初始化线程
}
public void run()
{
init(); //调用初始化方法
}
private synchronized void init() {
if (!initDone) //如果还没有初始化完毕
{
readRecordStore(); //读取游戏记录
tance(); //获得声音效果类的唯一实例
menuList = new MenuList(this); //初始化菜单
myCanvas = new escapeeCanvas(this); //初始化游戏画布
initDone = true; //标志位为真表示初始化完毕
}
第 24 页 共 42 页
杨永:基于J2ME的手机游戏设计 }
void splashScreenDone() {
init(); //检测是否初始化完毕,如果没有继续初始化
play(this).setCurrent(menuList); //在屏幕上显示游戏菜单 }
(2)屏幕切换
从菜单中选择开始游戏,首先初始化Canvas 的游戏数据,显示游戏画布,然后启动游
戏线程:
void menuListNewGame() {
(); //初始化游戏数据
play(this).setCurrent(myCanvas); //显示游戏画布
(); //启动游戏线程
}
从菜单中选择显示高分纪录,注意每次都动态生成一个高分纪录屏幕,使用完后就会销毁
以避免在不使用的时候占用堆内存:
void menuListHighScore() {
play(this).setCurrent(new HighScoreScreen(this)); //显示高分纪录屏幕
}
从菜单中选择游戏说明,和选择显示高分纪录类似: void
menuListInstructions() {
play(this).setCurrent(new InstructionsScreen(this));
//显示游戏介绍屏幕
}
游戏如果中断,从菜单中选择继续游戏,显示游戏画布并重启游戏线程: void
menuListContinue() {
play(this).setCurrent(myCanvas); //显示游戏画面
(); //启动游戏线程
}
从菜单中选择退出,调用quit 方法:
void menuListQuit()
{
quit(); //退出游戏
}
从游戏介绍退回菜单,将显示权交还游戏菜单:
void instructionsBack() {
play(this).setCurrent(menuList); //显示游戏菜单 }
从高分榜退回菜单,将显示权交还游戏菜单:
void highScoreBack()
{
play(this).setCurrent(menuList); //显示游戏菜单 }
从游戏中切换到菜单,需要中止游戏线程并且告知菜单游戏正在进行中,以便让菜单添加
继续游戏的选项:
void GameCanvasMenu()
{
(); //暂停游戏线程
eActive(true); //告知菜单游戏已经开始(暂停状态)
play(this).setCurrent(menuList); //显示游戏菜单 第 25 页
共 42 页
武汉科技大学中南分校毕业设计(论文) }
显示游戏结束画面,需要告诉GameOverScreen 类当前的最好成绩以及子弹的数目,同时
告诉菜单游戏已经结束:
void GameCanvasGameOver(long time,int BULLETS_NUM)
{
(); //中止游戏线程
eActive(false); //告知游戏已经结束
play(this).setCurrent(new GameOverScreen(this, time,
BULLETS_NUM)); //结束
画面
}
从游戏结束画面返回,在屏幕上显示菜单:
void gameOverDone()
{
play(this).setCurrent(menuList); //显示游戏菜单 }
(3)最佳纪录
读取方法的代码如下:
private void readRecordStore() {
hasBestTime = false; //读取记录还没有获得最好成绩
RecordStore rs = null;
ByteArrayInputStream bais = null; DataInputStream dis = null; try
{
rs = cordStore(RS_NAME, false); //记录名为RS_NAME
的字符串 byte[] data = ord(1); //读取第一条记录
bais = new ByteArrayInputStream(data);
dis = new DataInputStream(bais); bestTime = ng(); //读取长整型值
hasBestTime = true; //以及从记录中获得最佳成绩
}
catch (IOException ex)
{
// 捕获IO 异常
}
catch (RecordStoreException ex) {
// 捕获读取存储记录异常
}
finally
{
if (dis != null)
{
try
{
(); //关闭流
}
catch (IOException ex)
{
// 捕获IO 异常
}
}
if (bais != null)
{
第 26 页 共 42 页
杨永:基于J2ME的手机游戏设计 try
{
(); //关闭流
}
catch (IOException ex) {
//捕获IO 异常
}
}
if (rs != null)
{
try
{
ecordStore(); //关闭存储
}
catch (RecordStoreException ex) {
//捕获存储异常
}
}
}
}
除了读取存储之外,如果游戏产生了一个最新成绩,还需要保存到数据存储中去。保存方
法如下:
rivate void writeRecordStore() {
RecordStore rs = null; ByteArrayOutputStream baos = null;
DataOutputStream dos = null; try
{
rs = cordStore(RS_NAME, true);//带开数据存储存如果不存在则创建
baos = new ByteArrayOutputStream(); //输出字节流 dos = new
DataOutputStream(baos); //输出数据流
ong(bestTime); //写入最佳成绩
byte[] data = Array();
if (Records() == 0) //如果里面没有记录
{
ord(data, 0, ); //添加记录
}
else
{
ord(1, data, 0, );//如果存在记录,则将第一条设置为当前最佳成绩
}
}
catch (IOException ex) {
// 捕获IO 异常
}
catch (RecordStoreException ex) {
// 捕获数据存储异常
}
finally
{
第 27 页 共 42 页
武汉科技大学中南分校毕业设计(论文) if (dos != null)
{
try
{
(); //关闭流
}
catch (IOException ex) {
//捕获IO 异常
}
}
if (baos != null)
{
try
{
(); //关闭流
}
catch (IOException ex) {
//捕获IO 异常
}
}
if (rs != null)
{
try
{
ecordStore(); //关闭数据存储
}
catch (RecordStoreException ex)
{
//捕获数据存储异常
}
}
}
}
在读取游戏或者从玩家前面的游戏记录中获取到成绩之后,立刻写入rms 存储。通过比较
获得最佳成绩并保存的实现代码如下:
boolean checkBestTime(long time)
{
if (!hasBestTime || (time > bestTime)) //如果还没有最好成绩或者当前成绩比最好成绩长的时
候
{
hasBestTime = true; //设置标志位为真,表示有最好成绩 bestTime = time;
//上面两种情况下,把最好成绩bestTime 替换成当前成绩time
writeRecordStore(); //保存最好成绩
return true; //返回true 表明对最好成绩进行了更新操作 }
else
{
return false; //返回false 表明没有最新的成绩纪录产生 }
}
在生成最好成绩之后(无论是读取存储或者玩家在游戏中动态产生的),就需要让游戏结
束屏幕或者高分榜知道这个最好成绩:
long getBestTime()
第 28 页 共 42 页
杨永:基于J2ME的手机游戏设计
{
return hasBestTime ? bestTime : -1; }
(4)停止、销毁、退出程序
游戏的暂停、退出代码如下:
public void pauseApp()
{
Displayable current = play(this).getCurrent(); //获得当前设备的显示上下文 if (current == myCanvas) //如果屏幕上的显示内容为游戏画布
{
(); //中止游戏线程
}
}
public void destroyApp(boolean unconditional)
{
if (myCanvas != null)
{
(); //在销毁程序之前先停止游戏线程
}
}
private void quit()
{
destroyApp(false);
notifyDestroyed(); //告知系统已经销毁程序,可以完全退出
}
(5)加载图片资源
MIDlet 中实现了根据字符串类型的文件名来加载图片资源的通用方法,其他各个类都可以使用这个方法来加载图片。
static Image createImage(String filename)
{
Image image = null;
try
{
image = Image(filename); //根据文件名创建Image 对象 }
catch (ption ex) {
//捕获IO 异常
}
return image; //返回图片对象image
}
(6)游戏特效
其代码如下:(mills 代表持续的时间。)
void vibrate(int millis)
{
play(this).vibrate(millis); //手机震动,持续时间为millis }
void flashBacklight(int millis) {
play(this).flashBacklight(millis); //手机背景光闪烁,持续时间为millis }
2.游戏闪屏SplashScreen 类的实现
Splash 屏幕在屏幕中央显示图像。在第一次绘制屏幕后,它将图像释放作为垃圾回收(把图片设为null)并回调MIDlet 进行初始化工作。三秒钟后或第一次按键后,它再次回调MIDlet 显示游戏菜单。通过这种方法,MIDlet可在显示splash 屏幕的同时进行初始化。 第 29 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
(1)构造函数
SplashScreen 类是一个Canvas 类的子类,它的构造函数先获得一个对主类的引用,以便 于回调主类的方法,然后加载闪屏图片,并启动闪屏线程。
SplashScreen( escapeeMIDlet midlet) {
= midlet;
setFullScreenMode(true);
splashImage = Image("/");
new Thread(this).start();
}
(2)绘制屏幕
闪屏屏幕的绘制是在paint 方法中完成,当显示闪屏时会自动调用paint 方法。注意下面 是绘制具有轮廓的文本的有用诀窍:首先用轮廓颜色把它绘制四次,分别向上、下、左、右
偏移,然后在它的正常位置用文本颜色对其绘制。在游戏主屏幕中使用该方法要小心,因为
文本绘制可能很慢,而该方法使速度减慢为原来的五分之一。
public void paint(Graphics g)
{
int CanvasWidth = getWidth(); //获得画布宽度
int CanvasHeight = getHeight(); //获得画布高度
or(0x00FFFFFF); //画笔颜色设置为白色
ct(0, 0, CanvasWidth, CanvasHeight); //填充整个屏幕
or(0x00FF0000); //画笔颜色设置为红色
ct(1, 1, CanvasWidth-3, CanvasHeight-3); //在屏幕边缘绘制一个矩形边框 if (splashImage != null)
{
age(splashImage, CanvasWidth/2, CanvasHeight/2,
R | R); //在屏幕中央绘制闪屏图片
splashImage = null; //将图片对象设置为null,以便垃圾回收
}
t(t(_PROPORTIONAL,_BOLD,
_LARGE));
int centerX = CanvasWidth / 2;
int centerY = CanvasHeight / 2+60; or(0x00FFFFFF); //将画笔颜色设置为白色
drawText(g, centerX, centerY - 1); //分别绘制四次,相差1 个象素,呈现文本带有背景的感觉
drawText(g, centerX, centerY + 1); drawText(g, centerX - 1, centerY);
drawText(g, centerX + 1, centerY); or(0x00000000); //将画笔颜色设置为黑色
drawText(g, centerX, centerY); //绘制文本
ScreenPainted(); //回调midlet 的方法,通知程序在幕后做初始化 }
private void drawText(Graphics g, int centerX, int centerY)
{
int fontHeight = t().getHeight(); int textHeight = 2 *
fontHeight; //文本总的高度
int topY = centerY - textHeight / 2; //topY 用于定位文本的合适位置
ring("逃亡者游戏",centerX, topY, R |
);
ring("版本: " + Property("MIDlet-Version"),
centerX,topY + fontHeight,R | );
}
第 30 页 共 42 页
杨永:基于J2ME的手机游戏设计
(3)闪屏线程
闪屏线程的主要工作为接受玩家键盘事件退出或者等待3 秒退出,代码如下:
public void run()
{
synchronized(this)
{
try
{
wait(3000L); //等待3 秒
}
catch (InterruptedException e) {
//捕获线程中断异常
}
dismiss();
}
}
(4)结束线程
有两种可能会结束闪屏线程,一为在run 方法中线程等待3 秒后调用,二为玩家按下键 盘,触发键盘事件,调用keyPressed 方法,在这个方法中结束闪屏线程。 public synchronized void keyPressed(int keyCode)
{
dismiss();
}
dimiss 方法如下,它将回调midlet 的splashScreenDone 方法,显示游戏菜单: private void dismiss()
{
if (!dismissed)
{
dismissed = true;
ScreenDone();
}
}
3.游戏菜单MenuList 类的实现
菜单列表是在splash 屏幕之后,或者游戏结束时,或者游戏中用户按下一个非游戏键时(从而暂停了游戏)显示的屏幕。
(1)构造函数
MenuList 类是List 类的子类,并且实现了CommandListener 接口,它的构造函数为,首先它实现List 类的构造函数,然后添加了三个基本选项以及Command: MenuList(escapeeMIDlet midlet) {
super("逃亡者", IT); //实现父类List 的构造方法,指定List
名和选择方式 = midlet;
append("开始新游戏", null);//添加新游戏选项
append("高分记录", null); //添加高分纪录选项
append("游戏说明", null); //添加游戏说明选项
exitCommand = new Command("退出", , 1); //定义并添加退出软键 addCommand(exitCommand);
setCommandListener(this); //绑定侦听器侦听选项以及软键
}
(2)继续游戏选项
当游戏中间被玩家中止时,游戏菜单中将会多一个“继续游戏”的选项,这个选项添加 与否取决于外部传入的布尔值和gameActive 值,前者为外部通知菜单游戏是否运行,后者和继续游戏选项是否存在对应(初始情况下为false)。
第 31 页 共 42 页
武汉科技大学中南分校毕业设计(论文) void setGameActive(boolean active)
{
if (active && !gameActive) //如果游戏正在运行,且不存在“继续游戏”选项 {
gameActive = true;
insert(0, "继续游戏", null); //在选项顶部插入继续游戏选项 }
else if (!active && gameActive) //如果游戏不在运行,但存在“继续游戏”选项 {
gameActive = false;
delete(0); //删除继续游戏选项
}
}
(3)处理事件
游戏菜单的事件处理包括两种,一种是Command 触发的事件,这里为退出程序,另
一种是菜单选项的处理处理方式,根据选择不同回调midlet的相应方法,让midlet 来负责
屏幕的切换。
public void commandAction(Command c, Displayable d)
{
if (c == _COMMAND) {
int index = getSelectedIndex(); //获得选择项的序号
if (index != -1) // should never be -1
{
if (!gameActive)//如果不存在继续游戏选项,则序号往后移位,以便和case
选项对应
{
index++;
}
switch (index)
{
case 0: //继续游戏
stContinue(); break;
case 1: //新游戏
stNewGame(); break;
case 2: //高分纪录
stHighScore(); break;
case 3: //游戏介绍
stInstructions(); break;
default:
//按照逻辑不可能出现这种情况
break;
}
}
}
else if (c == exitCommand) //如果按下退出软键
{
stQuit(); //退出程序
2024年1月23日发(作者:汉阳煦)
【精品】:国内外手机游戏的研究现状
武汉科技大学中南分校毕业设计(论文)
目录
第一章 引言 ............................................... 1
1.1 国内外手机游戏的研究现状 ..................................................... 1
1.2 手机游戏的技术分类 ................................................................. 1
1.3 研究意义 .................................................................................... 2 第二章 基于J2ME的手机游戏开发平台概述 ................... 4
2.1 什么是J2ME ............................................................................... 4
2.2 J2ME 平台体系结构 ................................................................... 4
2.3
KVM ............................................................................................ 5
2.4
6
2.5移动信息设备描述(MIDP) .......................................................... 8
2.6MIDP 应用程序 ............................................................................ 8
2.7 MIDP UI 组件 ............................................................................. 9 第三章手机游戏开发的相关知识及工具 ...................... 12
3.1 手机游戏的画面 ........................................................................ 12
3.2手机游戏中的按键 ....................................................................
13
3.3线程使用.................................................................................... 14
3.4 手机硬件平台特点 ....................................................................
14
3.5 手机游戏开发工具软件 ............................................................ 15 第四章 手机游戏一“逃亡者”的设计与实现 ................. 17
4.1游戏描述.................................................................................... 17
4.2可行性研究 ................................................................................ 17
4.3游戏设计.................................................................................... 17
4.4详细编码设计 ............................................................................ 19
4.5程序打包、下载安装与运行 .................................................... 19
4.6 最后效果图 ............................................................................... 20 第五章 结束语 ............................................
21 参考文献 ................................................. 22 致
谢 ................................................. 23 附录 ..................................................... 24
第 1 页 共 42 页
杨永:基于J2ME的手机游戏设计
第一章 引言
1.1 国内外手机游戏的研究现状
近年来,因特网在国内迅速普及,导致了网络游戏的高速发展。同样手机的普及,导致了手机游戏市场呈现爆炸式的发展。尤其是国内外巨大的手机拥有量,更是让商家看到了商机,手机游戏市场利润将会十分丰厚。面对潜力如此巨大的手机游戏市场,各游戏开发商、运营商、服务商以及手机终端厂商等都纷纷开始了各自的应战准备,以便抢占商机。
诺基亚、索爱、摩托罗拉等各大手机厂商开始不断的提升手机在游戏方面的性能,同时还在手机操作系统方面采用开放式的平台,方便用户享受不同的
[1]手机游戏业务。而国内游戏开发商,如盛大、网易等公司,纷纷跻身手机游戏开发商行列。新浪、搜狐等著名的门户网站,也纷纷涉足手机游戏领域,相继开辟了各自的手机游戏频道和栏目,其他一些游戏网站也都全面加快了手机游戏开发的步伐。目前SUN公司的J2ME CLDC/MIDP环境和高通公司的BREW(Binary
Runtime Environment for Wireless)客户端程序是国内外游戏开发的两大主要平台。中国电信业巨头中国移动建立了无线Java增值服务体系,推出了基于SUN公司的J2ME 环境的“百宝箱”业务,包括游戏类、商务类、生活类等丰富的数据服务。中国移动用户只要使用支持Java的手机,通过GPRS的无线上网方式,访问移动梦网门户的“百宝箱”服务菜单,就能方便地下载各种由Java语言编写的应用程序。而中国联通与高通公司合作,采用高通公司的BREW平台技术,推出了“神奇宝典”业务,中国联通用户可以从联通公司的应用下载服务器上以无线方式下载应用程序。
1.2 手机游戏的技术分类
手机游戏按实现的技术分,可分为嵌入式游戏、浏览器游戏、基于J2ME和其它的解释语言的游戏、基于C++应用程序和其它编译语言的游戏等。
1. 嵌入式游戏
嵌入式游戏在出厂时就固化在手机的芯片中,像Nokia的“贪吃蛇”就是一个经典的例子。这些游戏是为手机量身定做,能够充分发挥特定手机的强大性能,从而达到其他类型的游戏所无法达到的效果,而且嵌入式游戏在运行过程中不会让用户产生费用。但是这些游戏是依据手机生产厂商的平台进行开发
[1] J2ME开发网?J2ME中文教程?PDF电子文档 ,2005-9-5
第 1 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
的,出厂时设置了几款游戏,玩家就只能在这几款游戏当中进行选择,而不能根据用户自己的喜好对游戏进行升级、删除等操作,所以嵌入式游戏的缺点也是明显的,无法给玩家带来新鲜感,玩家容易对固定的几款游戏产生厌倦。
2. 浏览器游戏
WAP是一种用手机上网的网络服务。进行WAP游戏时,通过手机自带的WAP浏览器来浏览手机网站上的页面,并通过页面中描述的内容来进行游戏。形式上类似于网上常见的一些心理测验之类的交互手段。WAP游戏没有图片和容量的限制,但这类游戏大多采用文字交互方式,这样游戏性就不强,缺乏直观感觉。而且在收费上,WAP游戏费用比较高,因为在游戏的过程中,您不仅需要向服务商交纳一定的费用,而且同时要向中国移动或中国联通交纳一定的流量费用。
. 基于C++应用程序和其它编译语言的游戏 3
使用C++应用程序和其它编译语言开发游戏也是一种较好的开发方式。编译语言程序能提供更好的控制用户界面,而且编写的应用程序相比用脚本语言编写的程序,效率更高、使用的内存更少,并且执行得更快。但由于这些编译语言往往不具有跨平台性,而且由于编译语言的特点,往往需要较长的开发周期。
4. 基于J2ME和其它解释语言的游戏
Java 2 Micro Edition (J2ME)是一种针对移动电话和PDA等小型设备的Java语言。采用J2ME极大的提高了手机支持游戏的能力。它有比WAP游戏更易控制的界面,J2ME游戏摆脱了纯文字交互的方式,它允许使用图形动画,并且可以通过无线网络连接到远程服务器。而且Java是面向对象程序设计的语言,它最大的特点是一次编写、到处运行,即平台无关性。现在支持Java的手机比较普及,它也已经成为目前比较好的移动游戏开发环境。
1.3 研究意义
对手机功能的扩充。
手机游戏成了电信增值业务中一项主要的应用,在公交车等公共场合不时会看到拿着手机玩游戏的人。相比较早开发的“贪吃蛇”、“俄罗斯方块”等手机游戏,如今的手机游戏,无论是从视觉效果、听觉效果还是游戏的可玩性来说,都要精彩的多。在全球,移动电话数量巨大,除美国之外,其他各个发达国家拥有手机的人数比拥有计算机的人数还多。在我国,手机拥有量甚至超过了美国的人口数量,而且每个月手机数量还正以惊人的速度递增着。手机市场的高速增加带动了手机游戏市场的急速膨胀,基于JAVA、BREW等技术平台
第 2 页 共 42 页
杨永:基于J2ME的手机游戏设计
[2]的手机游戏市场规模纷纷呈现几何增长态势。
[2] 林邦杰?Java程序设计入门教程?中国青年出版社,2001-9-15 第 3 页 共
42 页
武汉科技大学中南分校毕业设计(论文)
第二章 基于J2ME的手机游戏开发平台概述 2.1 什么是J2ME
J2ME 是SUN 公司针对嵌入式、消费类电子产品推出的开发平台,与J2SE 和J2EE 共同组成Java 技术的三个重要的分支。J2ME 实际上是一系列规范的集合,
由JCP 组织制定相关的Java Specification Request(JSR)并发布,各个厂商会按照规范在自己的产品上进行实现,但是必须要通过TCK 测试,这样确保
[3]兼容性。
2.2 J2ME 平台体系结构
J2ME 平台是由配置(Configuration)和简表(Profile)构成的。配置是提供给最大范围设备使用的最小类库集合,在配置中同时包含Java 虚拟机。简表是针对一系列设备提供的开发包集合。在J2ME 中还有一个重要的概念是可选包(Optional -Package),它是针对特定设备提供的类库,比如某些设备是支持蓝牙的,针对此功能J2ME 中制定了JSR82(Bluetooth API)提供了对蓝牙的支持。目前,J2ME 中有两个最主要的配置,分别是Connected Limited Devices
Configuration(CLDC)和Connected Devices Configuration(CDC)。他们是根
[4]据设备的硬件性能进行区分的。
CDC 的硬件参数:
(1) 2M 以上内存。
(2) 具有网络连接能力,通常为无线网络。
(3) 需要实现java 虚拟机规范的全部功能。
(4) 32 位或者64 位的处理器。
CLDC 的硬件参数:
(1) 512 KB 以下内存
(2) 有限能源供应(通常使用电池)。
(3) 有限或非持续网络连接。
(4) 简单的用户界面。
(5) 16 位或者32 位的处理器。
[3][4] 黄聪明?JAVA移动通信程序设计J2ME MIDP?清华大学出版社
第 4 页 共 42 页
杨永:基于J2ME的手机游戏设计
从上述的标准中我们不难看出CLDC 主要针对那些资源非常受限的设备比如手机、PDA、双工寻呼机等。而CDC 主要面对那些家电产品,比如机顶盒、汽车导航系统等。简表是以配置为基础的,例如Mobile Information Devices Profile
(MIDP)就是CLDC 上层的重要简表。与配置的纵向特性不同的是,简表是横向的。
-1是J2ME 体系结构的框图: 下图2
The J2ME Environment
J2ME Appliacation Layer
MIDLet
MIDLet Class Layer
MIDLet Application Manager
图2-1J2ME 体系结构框图
(1) 主机操作系统层(Host Operating System Layer):这一层为特定硬件设备的操作系统层。
(2) Java虚拟机层(Java Virtual Machine Layer):这一层是Java虚拟机的一个实现,它是为特定为特定设备的主机操作系统定制的,支持一个特定的J2ME配置。
(3) 配置层(Configuration Layer):配置层定义Java虚拟机的功能和特定类别设备上可用的Java类库的最小集。从某种程度上说,一个配置定义了Java平台的功能部件和库的共同性,开发者可以假设这些功能部件和库在属于某一特定类别的所有设备上都是可用的。这一层对用户是透明的,但它对描述的实现者非常重要。
(4) 描述层(Profile Laver):描述层定义了特定类别设备上可用的应用程序编程设备的主机操作系统定制的,支持一个特定的J2ME配置。
在手机上,KVM, CLDC, MIDP分别实现了J2ME体系结构中的Java虚拟机层、配置层和描述层。
2.3 KVM
CLDC 和 MIDP都是运行在Sun公司的KVM上。KVM是一个专门为小型、资源受限设备所设计的紧凑的、便携的Java虚拟机。Java虚拟机是Java程序语言的核心,只要Java程序在执行,Java虚拟机也必定在执行。Java虚拟机是实际执行Java程序的引擎,也是Java语言具有这么多优良特色的关键所在。当你执行Java程序时,程序内的指令其实并不是由硬件直接执行,而是由一个特别的软第 5 页
共 42 页
武汉科技大学中南分校毕业设计(论文)
件一一读取这些指令来执行的。简单地说,Java程序不是被底层的CPU直接执行,而是被“虚拟CPU”执行的,所谓的虚拟CPU其实就是计算机上执行的一个特别软件。虚拟机的优点甚多,比如移植方便,只需要移植虚拟机和相关的支持程序库到新的硬件架构上,所有上层的应用程序都不需要更动就完成移植了。虚拟机的另一个好处是它在计算机软硬件间加入一抽象层来分离和保护,
[5]可以防止恶作剧的程序暗中搞鬼。
2.4 CLDC
2000 年5 月,Java Community Process(JCP)公布了CLDC1.0 规范(即JSR30)。作为第一个面对小型设备的Java应用开发规范,CLDC是由包括Nokia,Motorola和Siemens在内的18 家全球知名公司共同协商完成的。CLDC是J2ME核心配置中的一个,可以支持一个或多个profile。其目标主要面向小型的、网络连
接速度慢、能源有限(主要是电池供电)且资源有限的设备,如手机、机顶盒、PDA
等。
CLDC 的核心是虚拟机和核心类库。虚拟机运行在目标操作系统之上,对下层的硬件提供必要的兼容和支持;核心类库提供操作系统所需的最小的软件需求。
1核心类
2库虚拟机
可选包
Profile
配置
操作系统
图2-2 CLDC 标准构架
2.4.1 CLDC 的目标
(1) 为小型的、资源受限的连接设备定义一个Java 平台标准。
(2) 允许向上述设备动态的传递Java 应用和内容。
(3) 使Java 开发人员能够轻松的在这些设备上进行应用开发。 2.4.2 CLDC
的整体需求
(1) 能运行在绝大多数的小型的、资源受限的连接设备上。
(2) 用CLDC 为上述设备开发的应用尽可能的不使用设备的本地系统软件。
[5] 卢军?J2ME应用程序开发手机、PDA程序开发捷径?中国铁道出版社
第 6 页 共 42 页
杨永:基于J2ME的手机游戏设计
(3) 定义能应用在绝大多数上述设备上的最小子集的规范。
(4) 保证在不同类型上述设备之间代码级的可移植性和互操作性。 2.4.3
CLDC 的硬件需求
由于CLDC 要面向尽可能多的设备,而这些设备所使用的硬件又各不相同。因此CLDC 规范中并没有指明需要某种硬件支持,只是对设备的最小内存进行了限制。CLDC 规范中要求硬件必须达到以下要求:
(1) 至少160KB 的固定内存以供虚拟机和CLDC 核心类库使用。
(2) 至少32KB 的动态内存以供虚拟机运行时使用(堆栈等)。
这里所说的固定内存是指拥有写保护,不会因关机而抹去的ROM。对于具体的设备的具体实现,这些需求也可能有变化。这里所规定的160KB 是CLDC 规范中的要求,实际也可以是128KB 左右。
2.4.4 CLDC 的软件需求
和硬件类似,CLDC 上运行的软件也是多种多样的。例如,有些设备支持多进程操作系统或者支持文件系统;而有些功能极其有限的设备并不需要文件系统。对于这些不确定性,CLDC只定义了软件所必须的最小集合。CLDC 规范中要求操作系统不需要支持多进程或是分址空间。
2.4.5 CLDC 的功能范围
在CLDC1.0 版本中定义了以下功能:
(1) Java 核心语言与Java 虚拟机的特性
(2) 核心Java 类库
(3) 输入/输出
(4) 对网络的支持
(5) 对安全性的支持
(6) 对国际化的支持
2.4.6 CLDC特征
(1) 安全
(2) 遵守Java语言规范
(3) 遵守Java虚拟机规范
(4) 要求类文件验证
J2EE和J2SE为桌面计算机和服务器的企业级应用和开发提供了非常丰富的库函数。不幸的是这些库需要几十兆的内存来运行,因此并不适合于资源受限的小型设备。所以CLDC针对小型受限设备重新制定了一个类库。为了保证应用程序的兼容性和可移植性,包括进CLDC的大多数类库都是J2SE中规定的子集,其它一些是由CLDC规定的专用于移动设备的类。包括:从J2SE中继承的第 7 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
[6]类、国际化支持类、系统属性类、CLDC专用类四个方面。 2.5移动信息设备描述(MIDP)
J2ME提供了描述的概念,使得可以为特定的设备家族定义相同的Java平台。描述可以满足两种明显不同的可移植性需求:
(1)描述为在一个特定的设备家族实现应用提供了完整的工具,比如传呼机、机顶盒、移动电话、洗衣机或智能玩具。
(2)可以创建一种描述来支持重要的、一致的一组应用,这些应用可能会在几各不同的设备上运行。
简单地说,描述就是应用和市场的设备家族之间的协议。处于同一个设备家族中的所有设备都必须实现其描述所定义的特征,并且要求应用只使用这个特定描述所提供的功能。在实现层次上,描述被简单地定义为应用在特定配置上的Java
API和类库的集合,同时为市场中特定的设备家族提供了附加的面向
[7]特定领域的功能。
现在,己经有了五个规范化了的描述,如表2-1
表2-1 五个规范化描述
描述名称 下层配置
Mobile information device profile(MIDP) CLDC
Personal digital assistant profile CLDC
Foundation profile CDC
Personal profile CDC
RMI profile CDC
2.6MIDP 应用程序
CLDC和MIDP组合起来为创建移动电话应用程序提供了完整的环境。MIDP应用程序或者称为MIDlet. 其模型如图2-3所示
[6] JSR-000139 Connected Limited Device Configuration 1.1 [7]
第 8 页 共 42 页
杨永:基于J2ME的手机游戏设计
The J2ME Environment
J2ME Appliacation Layer
MIDLet
MIDLet Class Layer
MIDLet Application Manager
图2-3MIDlet应用框
MIDlet 有三个状态,分别是pause、active 和destroyed。在启动一个MIDlet的时候,应用管理软件会首先创建一个MIDlet 实例并使得他处于pause
状态,
active 状态,也就是所说的运行状当startApp()方法被调用的时候MIDlet
进入
态。在active 状态调用destroyApp(booleanunconditional)或者pauseApp()方法可以使得MIDlet 进入destroyed 或者pause 状态。值得一提的是destroyApp(boolean
unconditional)方法,事实上,当destroyApp()方法被调用的时候,AMS 通知MIDlet 进入destroyed 状态。在destroyed 状态的MIDlet 必须释放了所有的资源,并且保存了数据。如果unconditional 为false的时候, MIDlet 可以在接到通知后抛出MIDletStateChangeException 而保持在当前状态,如果设置为true
的话,则必须立即进入destroyed状态。下图2-4说明了MIDlet 状态改变情况:
Start
startApp
Active Paused
pauseApp
destroyApp destroyApp
Destroyed
图2-4 MIDlet 状态图
2.7 MIDP UI 组件
In 组件与低级绘制相比,用在游戏开发上的机会较少,但还是会到。所谓UI组件,是指继承了类的
,,x,j
avam 等。
下图为我们展示了整个LCDUI 包的体系:
第 9 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
Display CommandLister
Ticker Displayable Command
Canvas Screen
Image
Graphics
Font
图2-5 LCDUI包的体系
Screen 类属于高级图形用户界面组件, Canvas 是低级图形用户界面组件,在同一时刻,只能有唯一一个Screen 或者Canvas 类的子类显示在屏幕上,我们可以调用Display 的set Current()的方法来将前一个画面替换掉,我们必须自行将前一个画面的状态保留起来,并自己控制整个程序画面的切换。同时我们可以运用d 类来给我们的提供菜单项目的功能,分别是:mmand、Command. CANCEL、、、、Comm 、 和,我们在Display
able对象中定义了add Command()和remove Command()两个方法,这就意味着我们可以在高级UI 和低级UI 中同时使用Command 类,同时我们通过注册Command
事件来达到事件处理的目的,即Command 必须与Command Listener 接口配合使用才能反映用户的动作。
与高级UI 相比,低级UI 就自由很多,任何时候我们可以调用repaint()产生重绘事件,调用完了repaint()会立刻返回,调用paint()回调函数则是由另一个专门的线程来完成。底层事件大致可分为三类:Press Events(按键事件),Action
Keys(动作按键,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
第 10 页 共 42 页
杨永:基于J2ME的手机游戏设计
中定义了一系列的动作事件:UP,DOWN,LEFT,RIGHT,GAME_A,GAME_B,GAME_C,GAME_D,当按下这些按键时会映射到我们自己为每个按键事件编写的方法,来完成一些动作。不过我们在MIDP2.0 里我们已经有专门的游戏开发包了,所以我在这里就不重点介绍了。
触控事件主要面向高端设备, 并非JTWI 要求强制支持的,其核心方法为:pointerPressed(),pointerReleased(),pointerDragged(),分别对应我们通常所用的移动设备手写笔的点,击,拖拽几个动作,我们在这三个方法里可以定义相应的事件处理函数。在索爱P910C 这样的高端手机上,支持屏幕的触控事件,我们在屏幕上点击,可以引发pointerPressed()函数,并传入当时位置的坐标,放开后,会引发pointerReleased()函数,同样也会传入坐标,具体的使用方法和keyPressed()以及keyReleased()大同小异。
第 11 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
第三章手机游戏开发的相关知识及工具 3.1 手机游戏的画面
MIDlet 类本身并没有提供直接操作画面显示的功能,因此在MIDlet类的子类中也没有直接操作画面显示的功能。因此,我们要使用提供了管理画面显示功能的y类。这个Display类可以y类的子类显示在画面上。
Displayable类的子类大致说来可以分为两种,分别为用来进行线与图形,图像的低级描绘类,与用于显示警告与文本的输入,选择列表等UI组件类。前者是类后者是dition.
类与其子类(Alert,FomList,TextBox类等)之旬的关系。
它们之旬的关系如下图3-1:
Object
Object
Display
Canvas Screen
TextBox Form List Alert
图3-1 画面显示类图
用来显示画面用的Display对象,可以从Display类的Static方法Display#getDisplay(MIDlet) 值获取。通过在获取的Display对象,就可以让Displayable对象显示在画面上。
MIDP中可以使用的图像格式为PNG格式。要获取图像,必须使用类的Static方法。Image类的Static方法,提供了从byte数据中提取Image对象,以及指定与MIDlet相同JAP文件的路径后获取对象的功能。创建Image对象的Static方法:
第 12 页 共 42 页
杨永:基于J2ME的手机游戏设计
(1)Image#createImage(byte[]imageData,int imageOffset,int imageLengt)
(2)Image#createImage(int souce) (3)Image#createImage(int width,int
height)
(4)Image#createImage(String name)
为了减少额外错误处理,在调用出来的时候要进行try-catch或throw。下面的代码展示了如何创建Image对象:
Image img;
Try{
img=Image(“/”)
}catch(ption e){
}
上一章提到了MIDP UI 的组件,这里不在做解释。Form类 是能够将一个以上的图像文本,Item类的子类(ChoiceGroup,DataField,Gauge,ImageItem)混合显示的组件。List类,与PC的UT组件中的List组件一样,是用来显示项目的列表,以让用户来进行选择为目的的组件。也可以是附有选择按钮的列表与附有复选框的列表。文 本 框 是一个允许用户进行编辑的文本区域。一个文本框有一个足以容纳的最大字符数量,具体的大小依赖于不同M工DP的实现或者是移动电话的存储器大小。在文本框中字符显示的顺序和格式由设备决定。当文本框中的字符数量大于一次被显示的字符数量时用户可以通过滚动来编辑一个文本框中的部分字符。Alert ,Form,List,TextBox各类的超类Screen由于与Canvas类一样,是继承了Displayable类,因此可以用Display # setCurrent
(Displayable)方法来将其显示在画面上。
3.2手机游戏中的按键
在MIDP中,每一个按键事件将产生一个按键代码。在MIDP的Canvas类中定义的按键代码如下所示:KEY_NUM0,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规范的移动设备上运行。
在Canvas类中,定义了一些通用按键值,游戏按键中的UP、DOWN、LEFT、RIGHT、FIRE、GAME_A、GAME_B,在MIDlet运行时,这些按键的
[8][9]按键值可以通过getKeyCode()方法确定。
[8] 洪维恩?Java 2面向对象程序设计?中国铁道出版社
第 13 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
3.3线程使用
我们所创建的动画,是使用线程把所准备的多张图像按顺序描绘出来。所谓的线程就是指程序的运行单位,使用线程可以同时进行处理。
在这里,为了要做出线程,我们会用到le接口。同样的处理虽然也可以用到类与类来进行,不过它们都需要创建出继承各类的另一个类,所以还不如使用Runnable接口。
将Runnable接口作为实现的类,必须将Runnable接口的run()方法重新定义。
在这个run()方法中,将要编写以线程所处理的内容。下面的代码为在run()方法内调用Canvas#repaint()方法来进行再描绘的范例。
Import .*
Class ThreadTest extends canvas implements Runnable{
Public void run( ){
Repaint( );
}
Protected void paint(Graphics g){
}
}
只在以Runnable接口为实现的类中再定义run() 方法,是不能让线程运行的。要运行的时候必须使用到Thread类。要调用Thread类的Constructor中指定Runnable接口参数的constructor,来产生Thread对象。接下来,要用产生的Thread接口来调用Thread # run() 方法来启用线程。
线程类由于会在Thread#start()方法被调用出来后调用Runnable#run( )方法,因此编写在run()方法中的处理将会被自动运行。线程的终止一般可通过两种方法实现;自然撤消或是被停止。自然撤消是指从线程的run()方法正常退出。
通 常,当一个应用程序停止运行,例如用户从一个主页切换到另一个主页
[10]时,它就会调用stop()方法来终止原主页中正在运行的所有线程。 3.4
手机硬件平台特点
手机作为一种资源有限的设备,和PC机相比,有以下一些特点: (1)处理器运算速度慢,远低于PC机的CPU运行速度。
(2)存储器容量小、存取速度慢。
[9] 焦祝军、张威?J2ME无线通信技术应用开发?北京希望电子出版社 [10] 范丹?J2ME在I-mode手机上的应用?现代计算机,2003年第7期
第 14 页 共 42 页
杨永:基于J2ME的手机游戏设计
(3)网络能力有限、带宽窄,并且因为手机的移动,容易导致手机网络地址的变化。
(4)输入/输出的多样性:手机不可能有PC机标准键盘那么多按键,也没有鼠标。它的显示能力也非常有限,譬如显示尺寸小、分辨率低等。 (5)手机由电池提供能源,会因为电池耗尽或接触不良造成经常断电。在编写
[14]手机应用程序时,必须对以上几个方面分别进行考虑。
3.5 手机游戏开发工具软件
J2ME Wireless Toolkit(J2MEWTK)是Sun公司所发布的官方版MIDP应用程序开发工具,它为编写和测试M工DP应用程序提供了一个完整的开发环境。J2ME
Wireless Toolkit()是制作手机用JAVA所必需的开发配套元件。
安装 J2MEWTK之前,一定要先安装Java2 SDK 1.3以上的版本。如果没有安装Java 2 SDK的话,J2MEWTK即使安装完成,也无法进行M工Dlet的开发工作。J2MEWTK提供菜单或按钮方式的命令。J2MEWTK中有相应的编译(集成了预验步骤)、打包、模拟运行的菜单(或按钮),以及其它辅助工具。J2SE SDK()是制作所有JAVA所必需的开发配套元件。
[11]这里介绍一下Java2 SDK及J2ME Wireless Toolkit的安装。
我们来安装制作JAVA所必需的开发配套元件J2SE SDK。先打开。
点击网页中的[Download J2SE SDK]链接,会出现了一个许可协议。仔细阅读完协议后,选中[Accept]然后再点击[Continue]。
这是选择安装程序的画面。因为你的PC的OS是WINDOWS,所以你可以试着点击[Windows Installation, Multi-language],来下载安装程序。
启动安装程序后,会出现一个许可协议的画面。看完后选同意,然后点击[Next]。
接下来,选择要安装的程序和安装到的地址。这里安装的程序就用默认的程序,安装地址也用默认的[c:j2sdk1.4.2_05]。
设定数据库文件夹,这里我们也用默认的设置。点击[Next],便开始安装了。
用安装软件安装完毕后,就要开始设定JAVA使用的环境。用鼠标右键点击桌面上“我的电脑”图标,在显示选单中选择“属性”。
打开“系统属性”,选择上面选单的“高级”,点击“环境变量”按钮,出现环
[14] 赵海廷?java语言程序设计?2005-8-8 [11] 佚名?JAVA教程
第 15 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
境变量设定窗口。
在“用户变量”和“系统变量”的表里如果没有“Path”变量,就点击“新建”。
在“变量名”一栏输入“Path”,“变量值”栏里输入刚才安装的 J2SE SDK的文件夹里“bin”文件夹的路径。这里设定为[c:j2sdk1.4.2_05bin]。输完后点击“确定”键。
下面就让我们来安装手机Java开发元件J2ME Wireless Toolkit。打开,点击网页下部的[Download]按键。
看完后选择[Accept],然后点击[Continue]。于是显示安装程序选择画面,点击[Windows Platform]的安装程序,并下载。
出现Wireless Toolkit的安装画面。选择[Next]。
下面是许可协议的画面,看完后选择[Yes]。
设定正在安装的J2SDK的路径。这里点击刚才安装J2SE SDK的[Browse..]键,设定[c:j2sdk1.4.2_05],设定完后,点击[Next]。
接下来设定安装WirelessToolkit的文件夹。这里使用预设的[c:WTK104],点击[Next]。
在程序文件夹进行注册,这里使用预设的[J2ME Wireless
Toolkit1.0.4_01],然后点击[Next]。
然后是设定的确认画面。若确认正确,点击[Next]。
安装完毕后点击[Finish]键,结束安装。
下面说明一下J2ME手机游戏开发环境:
Java手机游戏的真实运行环境是Java手机。一般来说,Java游戏的开发是先在PC机上模拟,模拟成功后再打包下载到手机上。本文的模拟环境是:
(1)系统环境Windows 2000
(2)平台支持J2SDK-1.4
(3)开发工具:采用MOTO-J2ME-SDK-5.2.1模拟器。
第 16 页 共 42 页
杨永:基于J2ME的手机游戏设计
第四章 手机游戏一“逃亡者”的设计与实现 4.1游戏描述
“逃亡者”是一款选取了一款PC 小游戏作为范例移植到手机上,它的中文名为《是男人就撑过30 秒》,虽然看似简单,但绝对有挑战性~这是总结了无数日本纵版飞行射击游戏中的武器而研究出的特殊训练软件,专门用来训练“战斗机”飞行员。在漆黑一片的宇宙中,停着一架小飞船,突然四面八方出现很多黄色的小点向小飞船聚集过来,小飞船凭借速度优势和飞行技术从黄点之间的夹缝中飞过,之后又落入新的包围圈中,直至被黄点击毁。坚持的时间越长,就说明水平越高。持续不同的时间会得到不同的评价。如图4-1 所示是它原来的游戏画面。
图4-1 《特训:是男人就撑过30 秒》游戏画面 4.2可行性研究
1.技术可行性:手机 游 戏 “逃亡者”是一款较为小型的手机游戏,根据已有的手机游戏设计经验,利用J2ME来可以实现游戏的功能。根据己往的设计进度,一款小型规模的手机游戏大概有2000,3000行代码。
2.操作可行性:该款游戏在所有支持JAVA的手机上都可运行,按键简单,易
[12]于操作。
4.3游戏设计
在进入游戏之前先显示闪屏图片,当用户按下键盘或等待3 秒后,进入游戏菜单。初始情况下,游戏菜单有三个选项,它们分别是开始游戏,游戏说明和高分记录。选择开始新游戏则进入游戏,在游戏中如果按下非游戏键盘则中断游戏返回菜单,此时菜单中增加了一个继续游戏的选项,可以返回游戏也可
[12] Jason Lam、Deaboway Chou译?J2ME游戏开发(第一版)?PDF电子文档
第 17 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
以重新开始新的游戏。当游戏结束时则进入游戏结束屏
幕,屏幕上显示了玩家的成绩和等级,以及游戏的最好成绩,如果当前成绩是最好成绩,则手机震动并播放音乐庆祝成功。在菜单中选择游戏说明或者高分纪录,则进入相应的屏幕,它们都能用“后退”软键返回菜单。菜单中的退出选
[13]项用于退出程序。游戏的流程如图4-3所示。
闪屏
新游戏 退出 游戏说明
最高记录
继续游戏
非游戏
操作
游戏 游戏说明 最高记录
Back Back 游戏
结束
游戏成绩
等级
最好成绩
图4-3 游戏系统流程图
程序中一个有10 个类,其中MIDlet 主类负责各个屏幕的切换,它们是闪屏屏幕、菜单、介绍屏幕、高分屏幕、游戏屏幕,游戏结束屏幕。游戏中使用到的类为SoundEffects(音效)、Bullets(子弹)、Escapee(逃亡小飞机)。程序的类结构如图4-4 所示。
SoundEffect
s
BulletescapeeCanvas s :GameCanvas escapeeMIDlet SplashScreeSprite
n :MIDlet
:Cancas
Escapee
:Sprite
GameOverScreeHighScoreSCreeInstructionsScreen MenuList
n n :From :List
:Canvas :Form
图4-2 游戏总体类图
下面介绍游戏线程:
[13] 李振鹏 、龚剑?J2ME手机游戏开发技术详解
第 18 页 共 42 页
杨永:基于J2ME的手机游戏设计
游戏的线程主要由三个部分组成:检测键盘输入(与玩家交互),更新游戏场景(处理游戏逻辑),绘制游戏画布。基本上所有的2D 游戏都可以按照这三个模块来设计,三个模块相互联系又互相联系,按照模块的思想来实现游戏线程将更加面向对象和便于理解。如果程序运行快于预期速度会使玩家感觉到抖动,从而影响游戏效果,因此还需要检测每帧的运行时间,如果过快则等待一段时间,如果过慢则挂起当前线程允许其他线程执行。线程的模块如图4-3所示:
检测键盘输入 更新游戏场景 绘制游戏画布
绘制缓冲区到
屏幕
否
是否快于挂起当前线程 预期速度
是
挂起等待
图4-3 游戏线程模块图
4.4详细编码设计
逃亡者游戏一共实现了几个类包括用于关于游戏外部的闪屏类、菜单类、高分屏幕类、简介屏幕类、结束屏幕类,以及用于游戏本身的游戏画布类、子弹类、逃亡飞机类和声音效果类。
详情见附录。
4.5程序打包、下载安装与运行
J2ME Wireless Toolkit 能自动对 MIDlet 套件进行打包。打包产生两个文件,即一个MIDlet 描述符和一个MIDlet套件JAR。描述符是一个小文本文件,包含有关 MIDlet 套件的信息。JAR 包含组成 MIDlet 套件的类文件和资源。
第 19 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
4.6 最后效果图
图4-6游戏运行画面(一) 图4-7 游戏运行画面(二) 图4-8 游戏结束画面
第 20 页 共 42 页
杨永:基于J2ME的手机游戏设计
第五章 结束语
本文以基于J2ME平台的手机游戏的功能开发为线索,进行了相关理论研究,实验和项目开发。首先介绍了J2ME的用途和基于J2ME平台手机开发的国内外发展情况,然后研究介绍了J2ME平台的特点和手机游戏开发的关键知识点。最后以如何在J2ME环境下实现一款射击类手机游戏的开发过程做了一个详细的介绍。其主要工作为:
1.研究介绍了J2ME平台的用途和基于J2ME平台手机开发的国内外发展情况。
2.研究介绍了J2ME平台的特性和体系结构。重点介绍了MIDP类库,应用程序的体系结构,程序开发周期,工具和实例。
3.研究介绍了J2ME游戏开发的关键技术知识。
4.实现了一款射击类手机游戏一“逃亡者”,重点解决了游戏角色的表示,游戏角色及游戏流程的控制,对游戏按键事件的处理,并对整个游戏开发过程做了一个详细的介绍。
第 21 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
参考文献
[1] J2ME开发网?J2ME中文教程?PDF电子文档 ,2005-9-5
-9-15 [2] 林邦杰?Java程序设计入门教程?中国青年出版社,2001
[3] [4] 黄聪明?JAVA移动通信程序设计J2ME MIDP?清华大学出版社 [5] 卢军?J2ME应用程序开发手机、PDA程序开发捷径?中国铁道出版社 [6] JSR-000139
Connected Limited Device Configuration 1.1
[7]
[8] 洪维恩?Java 2面向对象程序设计?中国铁道出版社
[9] 焦祝军、张威?J2ME无线通信技术应用开发?北京希望电子出版社 [10] 范丹?J2ME在I-mode手机上的应用?现代计算机,2003年第7期 [11] 佚名?JAVA教程
[12] Jason Lam、Deaboway Chou译?J2ME游戏开发(第一版)?PDF电子文档
[13] 李振鹏 、龚剑?J2ME手机游戏开发技术详解
[14] 赵海廷?java语言程序设计?2005-8-8
[15] JAVA手机网[]
[16] 温尚书?J2ME无线通信实用案例教程?清华大学出版社
[17] Jason Lam, Deaboway Chou译?J2ME游戏开发(第一版)?PDF电子文档
[18] 、?程序设计教程?清华大学出版社
第 22 页 共 42 页
杨永:基于J2ME的手机游戏设计
致 谢
首先感谢我的指导老师罗奇导师,他在我的毕业设计过程中提出了指导性的方案和架构,特别是指引我阅读相关的资料和书籍,使我更能迅速学习掌握知识并完成了这个毕业设计。
感谢答辩组对本毕业设计的考核,如果可以得到各位专家的认可将对我的学习和工作给予极大的鼓励。你们客观的评价和建议我将牢记在心,在今后的发展中扬长避短,更加努力的严格要求自己。
感谢学校对我的培育,让我从思想上素质上知识上得到很大的提高,本科学习中的各科老师的悉心教导让我掌握了基本知识.
感谢我的同学在设计完成前后对我的得力帮助,没有同学的共同学习进步也许就没法完成设计,没有同学对程序的测试,也许就难以发现一些潜在的错误,在此一并表示感谢。
在此一并祝愿学校领导、老师、同学工作顺利,事业更上一层楼;同时也祝愿学校更加辉煌。
第 23 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
附录
根据详细设计对各个类进行编码实现:
1.主类escapeeMIDlet 的实现
MIDlet 被用作一个状态机来管理各种屏幕以及它们之间的转换。例如,当显示splash 屏幕时,该类和类SplashScreen(通过方法splashScreenPainted 和
splashScreenDone)共同在方法init 中完成背景初始化。而使用方法readRecordStore 和writeRecordStore 在一个名为 “BESTTIME”的记录存储区中保存最高得分。
(1)实现闪屏
游戏的最开始将会出现一幅和游戏相关的图片,它会停留一小段时间,然后才进入游戏菜单。游戏闪屏使用得当将会增加整个游戏的视觉效果,而且虽然画面在此期间停留不动,后台程序却是忙碌的,一般在此期间完成基本的初始化工作。在startApp 方法中,将游戏的显示权交给闪屏。如果中断之前的显示内容为游戏画布,则重新启动画布的线程,显示权仍然交给画布。
public void startApp()
{
Displayable current = play(this).getCurrent(); //获得关于显示的设备上下文 if (current == null)
{
play(this).setCurrent(new SplashScreen(this)); //第一次将显示闪屏 }
else
{
if (current == myCanvas)
{
(); //重新开始游戏线程
}
play(this).setCurrent(current); //显示游戏画布内容
}
}
关于闪屏实现的代码如下:
void splashScreenPainted()
{
new Thread(this).start(); //启动幕后的初始化线程
}
public void run()
{
init(); //调用初始化方法
}
private synchronized void init() {
if (!initDone) //如果还没有初始化完毕
{
readRecordStore(); //读取游戏记录
tance(); //获得声音效果类的唯一实例
menuList = new MenuList(this); //初始化菜单
myCanvas = new escapeeCanvas(this); //初始化游戏画布
initDone = true; //标志位为真表示初始化完毕
}
第 24 页 共 42 页
杨永:基于J2ME的手机游戏设计 }
void splashScreenDone() {
init(); //检测是否初始化完毕,如果没有继续初始化
play(this).setCurrent(menuList); //在屏幕上显示游戏菜单 }
(2)屏幕切换
从菜单中选择开始游戏,首先初始化Canvas 的游戏数据,显示游戏画布,然后启动游
戏线程:
void menuListNewGame() {
(); //初始化游戏数据
play(this).setCurrent(myCanvas); //显示游戏画布
(); //启动游戏线程
}
从菜单中选择显示高分纪录,注意每次都动态生成一个高分纪录屏幕,使用完后就会销毁
以避免在不使用的时候占用堆内存:
void menuListHighScore() {
play(this).setCurrent(new HighScoreScreen(this)); //显示高分纪录屏幕
}
从菜单中选择游戏说明,和选择显示高分纪录类似: void
menuListInstructions() {
play(this).setCurrent(new InstructionsScreen(this));
//显示游戏介绍屏幕
}
游戏如果中断,从菜单中选择继续游戏,显示游戏画布并重启游戏线程: void
menuListContinue() {
play(this).setCurrent(myCanvas); //显示游戏画面
(); //启动游戏线程
}
从菜单中选择退出,调用quit 方法:
void menuListQuit()
{
quit(); //退出游戏
}
从游戏介绍退回菜单,将显示权交还游戏菜单:
void instructionsBack() {
play(this).setCurrent(menuList); //显示游戏菜单 }
从高分榜退回菜单,将显示权交还游戏菜单:
void highScoreBack()
{
play(this).setCurrent(menuList); //显示游戏菜单 }
从游戏中切换到菜单,需要中止游戏线程并且告知菜单游戏正在进行中,以便让菜单添加
继续游戏的选项:
void GameCanvasMenu()
{
(); //暂停游戏线程
eActive(true); //告知菜单游戏已经开始(暂停状态)
play(this).setCurrent(menuList); //显示游戏菜单 第 25 页
共 42 页
武汉科技大学中南分校毕业设计(论文) }
显示游戏结束画面,需要告诉GameOverScreen 类当前的最好成绩以及子弹的数目,同时
告诉菜单游戏已经结束:
void GameCanvasGameOver(long time,int BULLETS_NUM)
{
(); //中止游戏线程
eActive(false); //告知游戏已经结束
play(this).setCurrent(new GameOverScreen(this, time,
BULLETS_NUM)); //结束
画面
}
从游戏结束画面返回,在屏幕上显示菜单:
void gameOverDone()
{
play(this).setCurrent(menuList); //显示游戏菜单 }
(3)最佳纪录
读取方法的代码如下:
private void readRecordStore() {
hasBestTime = false; //读取记录还没有获得最好成绩
RecordStore rs = null;
ByteArrayInputStream bais = null; DataInputStream dis = null; try
{
rs = cordStore(RS_NAME, false); //记录名为RS_NAME
的字符串 byte[] data = ord(1); //读取第一条记录
bais = new ByteArrayInputStream(data);
dis = new DataInputStream(bais); bestTime = ng(); //读取长整型值
hasBestTime = true; //以及从记录中获得最佳成绩
}
catch (IOException ex)
{
// 捕获IO 异常
}
catch (RecordStoreException ex) {
// 捕获读取存储记录异常
}
finally
{
if (dis != null)
{
try
{
(); //关闭流
}
catch (IOException ex)
{
// 捕获IO 异常
}
}
if (bais != null)
{
第 26 页 共 42 页
杨永:基于J2ME的手机游戏设计 try
{
(); //关闭流
}
catch (IOException ex) {
//捕获IO 异常
}
}
if (rs != null)
{
try
{
ecordStore(); //关闭存储
}
catch (RecordStoreException ex) {
//捕获存储异常
}
}
}
}
除了读取存储之外,如果游戏产生了一个最新成绩,还需要保存到数据存储中去。保存方
法如下:
rivate void writeRecordStore() {
RecordStore rs = null; ByteArrayOutputStream baos = null;
DataOutputStream dos = null; try
{
rs = cordStore(RS_NAME, true);//带开数据存储存如果不存在则创建
baos = new ByteArrayOutputStream(); //输出字节流 dos = new
DataOutputStream(baos); //输出数据流
ong(bestTime); //写入最佳成绩
byte[] data = Array();
if (Records() == 0) //如果里面没有记录
{
ord(data, 0, ); //添加记录
}
else
{
ord(1, data, 0, );//如果存在记录,则将第一条设置为当前最佳成绩
}
}
catch (IOException ex) {
// 捕获IO 异常
}
catch (RecordStoreException ex) {
// 捕获数据存储异常
}
finally
{
第 27 页 共 42 页
武汉科技大学中南分校毕业设计(论文) if (dos != null)
{
try
{
(); //关闭流
}
catch (IOException ex) {
//捕获IO 异常
}
}
if (baos != null)
{
try
{
(); //关闭流
}
catch (IOException ex) {
//捕获IO 异常
}
}
if (rs != null)
{
try
{
ecordStore(); //关闭数据存储
}
catch (RecordStoreException ex)
{
//捕获数据存储异常
}
}
}
}
在读取游戏或者从玩家前面的游戏记录中获取到成绩之后,立刻写入rms 存储。通过比较
获得最佳成绩并保存的实现代码如下:
boolean checkBestTime(long time)
{
if (!hasBestTime || (time > bestTime)) //如果还没有最好成绩或者当前成绩比最好成绩长的时
候
{
hasBestTime = true; //设置标志位为真,表示有最好成绩 bestTime = time;
//上面两种情况下,把最好成绩bestTime 替换成当前成绩time
writeRecordStore(); //保存最好成绩
return true; //返回true 表明对最好成绩进行了更新操作 }
else
{
return false; //返回false 表明没有最新的成绩纪录产生 }
}
在生成最好成绩之后(无论是读取存储或者玩家在游戏中动态产生的),就需要让游戏结
束屏幕或者高分榜知道这个最好成绩:
long getBestTime()
第 28 页 共 42 页
杨永:基于J2ME的手机游戏设计
{
return hasBestTime ? bestTime : -1; }
(4)停止、销毁、退出程序
游戏的暂停、退出代码如下:
public void pauseApp()
{
Displayable current = play(this).getCurrent(); //获得当前设备的显示上下文 if (current == myCanvas) //如果屏幕上的显示内容为游戏画布
{
(); //中止游戏线程
}
}
public void destroyApp(boolean unconditional)
{
if (myCanvas != null)
{
(); //在销毁程序之前先停止游戏线程
}
}
private void quit()
{
destroyApp(false);
notifyDestroyed(); //告知系统已经销毁程序,可以完全退出
}
(5)加载图片资源
MIDlet 中实现了根据字符串类型的文件名来加载图片资源的通用方法,其他各个类都可以使用这个方法来加载图片。
static Image createImage(String filename)
{
Image image = null;
try
{
image = Image(filename); //根据文件名创建Image 对象 }
catch (ption ex) {
//捕获IO 异常
}
return image; //返回图片对象image
}
(6)游戏特效
其代码如下:(mills 代表持续的时间。)
void vibrate(int millis)
{
play(this).vibrate(millis); //手机震动,持续时间为millis }
void flashBacklight(int millis) {
play(this).flashBacklight(millis); //手机背景光闪烁,持续时间为millis }
2.游戏闪屏SplashScreen 类的实现
Splash 屏幕在屏幕中央显示图像。在第一次绘制屏幕后,它将图像释放作为垃圾回收(把图片设为null)并回调MIDlet 进行初始化工作。三秒钟后或第一次按键后,它再次回调MIDlet 显示游戏菜单。通过这种方法,MIDlet可在显示splash 屏幕的同时进行初始化。 第 29 页 共 42 页
武汉科技大学中南分校毕业设计(论文)
(1)构造函数
SplashScreen 类是一个Canvas 类的子类,它的构造函数先获得一个对主类的引用,以便 于回调主类的方法,然后加载闪屏图片,并启动闪屏线程。
SplashScreen( escapeeMIDlet midlet) {
= midlet;
setFullScreenMode(true);
splashImage = Image("/");
new Thread(this).start();
}
(2)绘制屏幕
闪屏屏幕的绘制是在paint 方法中完成,当显示闪屏时会自动调用paint 方法。注意下面 是绘制具有轮廓的文本的有用诀窍:首先用轮廓颜色把它绘制四次,分别向上、下、左、右
偏移,然后在它的正常位置用文本颜色对其绘制。在游戏主屏幕中使用该方法要小心,因为
文本绘制可能很慢,而该方法使速度减慢为原来的五分之一。
public void paint(Graphics g)
{
int CanvasWidth = getWidth(); //获得画布宽度
int CanvasHeight = getHeight(); //获得画布高度
or(0x00FFFFFF); //画笔颜色设置为白色
ct(0, 0, CanvasWidth, CanvasHeight); //填充整个屏幕
or(0x00FF0000); //画笔颜色设置为红色
ct(1, 1, CanvasWidth-3, CanvasHeight-3); //在屏幕边缘绘制一个矩形边框 if (splashImage != null)
{
age(splashImage, CanvasWidth/2, CanvasHeight/2,
R | R); //在屏幕中央绘制闪屏图片
splashImage = null; //将图片对象设置为null,以便垃圾回收
}
t(t(_PROPORTIONAL,_BOLD,
_LARGE));
int centerX = CanvasWidth / 2;
int centerY = CanvasHeight / 2+60; or(0x00FFFFFF); //将画笔颜色设置为白色
drawText(g, centerX, centerY - 1); //分别绘制四次,相差1 个象素,呈现文本带有背景的感觉
drawText(g, centerX, centerY + 1); drawText(g, centerX - 1, centerY);
drawText(g, centerX + 1, centerY); or(0x00000000); //将画笔颜色设置为黑色
drawText(g, centerX, centerY); //绘制文本
ScreenPainted(); //回调midlet 的方法,通知程序在幕后做初始化 }
private void drawText(Graphics g, int centerX, int centerY)
{
int fontHeight = t().getHeight(); int textHeight = 2 *
fontHeight; //文本总的高度
int topY = centerY - textHeight / 2; //topY 用于定位文本的合适位置
ring("逃亡者游戏",centerX, topY, R |
);
ring("版本: " + Property("MIDlet-Version"),
centerX,topY + fontHeight,R | );
}
第 30 页 共 42 页
杨永:基于J2ME的手机游戏设计
(3)闪屏线程
闪屏线程的主要工作为接受玩家键盘事件退出或者等待3 秒退出,代码如下:
public void run()
{
synchronized(this)
{
try
{
wait(3000L); //等待3 秒
}
catch (InterruptedException e) {
//捕获线程中断异常
}
dismiss();
}
}
(4)结束线程
有两种可能会结束闪屏线程,一为在run 方法中线程等待3 秒后调用,二为玩家按下键 盘,触发键盘事件,调用keyPressed 方法,在这个方法中结束闪屏线程。 public synchronized void keyPressed(int keyCode)
{
dismiss();
}
dimiss 方法如下,它将回调midlet 的splashScreenDone 方法,显示游戏菜单: private void dismiss()
{
if (!dismissed)
{
dismissed = true;
ScreenDone();
}
}
3.游戏菜单MenuList 类的实现
菜单列表是在splash 屏幕之后,或者游戏结束时,或者游戏中用户按下一个非游戏键时(从而暂停了游戏)显示的屏幕。
(1)构造函数
MenuList 类是List 类的子类,并且实现了CommandListener 接口,它的构造函数为,首先它实现List 类的构造函数,然后添加了三个基本选项以及Command: MenuList(escapeeMIDlet midlet) {
super("逃亡者", IT); //实现父类List 的构造方法,指定List
名和选择方式 = midlet;
append("开始新游戏", null);//添加新游戏选项
append("高分记录", null); //添加高分纪录选项
append("游戏说明", null); //添加游戏说明选项
exitCommand = new Command("退出", , 1); //定义并添加退出软键 addCommand(exitCommand);
setCommandListener(this); //绑定侦听器侦听选项以及软键
}
(2)继续游戏选项
当游戏中间被玩家中止时,游戏菜单中将会多一个“继续游戏”的选项,这个选项添加 与否取决于外部传入的布尔值和gameActive 值,前者为外部通知菜单游戏是否运行,后者和继续游戏选项是否存在对应(初始情况下为false)。
第 31 页 共 42 页
武汉科技大学中南分校毕业设计(论文) void setGameActive(boolean active)
{
if (active && !gameActive) //如果游戏正在运行,且不存在“继续游戏”选项 {
gameActive = true;
insert(0, "继续游戏", null); //在选项顶部插入继续游戏选项 }
else if (!active && gameActive) //如果游戏不在运行,但存在“继续游戏”选项 {
gameActive = false;
delete(0); //删除继续游戏选项
}
}
(3)处理事件
游戏菜单的事件处理包括两种,一种是Command 触发的事件,这里为退出程序,另
一种是菜单选项的处理处理方式,根据选择不同回调midlet的相应方法,让midlet 来负责
屏幕的切换。
public void commandAction(Command c, Displayable d)
{
if (c == _COMMAND) {
int index = getSelectedIndex(); //获得选择项的序号
if (index != -1) // should never be -1
{
if (!gameActive)//如果不存在继续游戏选项,则序号往后移位,以便和case
选项对应
{
index++;
}
switch (index)
{
case 0: //继续游戏
stContinue(); break;
case 1: //新游戏
stNewGame(); break;
case 2: //高分纪录
stHighScore(); break;
case 3: //游戏介绍
stInstructions(); break;
default:
//按照逻辑不可能出现这种情况
break;
}
}
}
else if (c == exitCommand) //如果按下退出软键
{
stQuit(); //退出程序