JAVA入门 基于Java的移动游戏开发
如果读者有Java编程经验,尤其是AWT和SWING的Java GUI开发经验将十分有助于理解本文,尽管不是必需的。
一、 引言
近来,移动游戏在提供个人娱乐方面变得越来越流行。这种流行使得移动游戏给手机用户,游戏出版商和手持设备制造者带来丰厚的利润;移动游戏,在给游戏开发者和相关人员带来无数商机的同时,处于极为重要的枢纽位置。据估计,到2009年,全世界的手机玩家有望达到两亿两千万之多,移动游戏业将被规划并扩展到一个更高层次,为手机用户和手持设备制造者带来更大的利润份额。
移动游戏可以分为三大类:
1、嵌入式游戏:被硬编码到移动手持设备系统中的游戏,并随着设备一同发布。不久就会过时。例如:随着诺基亚手机一同发行的贪吃蛇游戏。
2、SMS游戏:通过发送文本消息来玩的游戏-例如,把SMS消息发送到游戏服务器-该服务器处理这些SMS消息,然后再通过SMS消息形式发送回结果。经常是以在线竞赛和测验形式出现。并不很流行,因为游戏的费用将随着把每一个SMS发送到游戏服务器而逐步增加。
3、浏览器游戏:这些游戏可以使用移动电话的内嵌微型浏览器(专用于移动设备的网络浏览器)来玩,在线或离线的方式都可以。玩家可以通过自己的手持设备或一个第三方游戏供给者的游戏Web站点的方式在线玩这样的游戏,或下载它们后离线玩。这一类游戏又有很多种类,例如单人或者多人游戏,网络游戏,离线游戏,街机游戏,等等。
在这三种类型中,浏览器游戏是今天最流行的移动游戏类型,这是因为它们具有创新性和丰富的多媒体内容,引人入胜的表达与SMS游戏相比的低价位优势。本文将重点讨论浏览器游戏开发。今后,术语"移动游戏"在本文专指"浏览器游戏"。
注意:本文集中于讨论2D游戏开发。因为今天流行的大部分的数字移动电话有很有限的资源(小的屏幕,有限的内存和图形支持,繁琐的键盘输入),所以时下最适合于这些设备的也是最具有商业可行性的游戏是2D游戏。但是,随着移动电话能力的不断提高,3D游戏在不久的将来将广为流行。
移动游戏可用C++,Java(J2ME),还有Qualcomm公司的Binary Runtime Environment for Wireless(BREW)平台来进行开发。
二、 为什么选择Java进行移动游戏开发?
尽管C++能够被编译成本机代码并且可以直接存取本机系统资源,以及与BREW(它允许开发者使用任何希望的语言,包括C++,Java,XML和Flash)相结合为移动游戏开发者提供端到端的解决方案,但是Java仍然是进行移动游戏开发的最流行的选择。Java,或更精确的说是Java 2微型版本(J2ME)平台,被认为是开发移动游戏的最方便的语言。(要更多地了解J2ME,请参考"What is Java 2 Micro Edition?")。J2ME如此流行的背后动力包括:
- J2ME遵循为大多数手持设备生产商所支持的工业标准,如今大多数的移动电话都支持Java开发。
- J2ME是一个自由的和开放的平台。这使得开发人员投资很少,但却提供给他们必需的灵活性以及大量的支持。
- 它的高度可移植的特性("书写一次到处运行")保证一部为一个品牌/类型的手持设备开发的游戏应用程序,将可以工作在其它类型的支持Java的手持设备品牌/类型上。
- 它特别为小型设备进行了优化,是轻量级的,高度安全的,因为在其上开发的应用程序不能存取或者影响运行在该手持设备上的其它应用程序。
- J2ME包含移动信息设备轮廓(MIDP)API,它的设计是为专门开发包括手机在内的移动设备应用程序,但切记它们的局限性和约束条件。而且,最新的MIDP 2.0版自己提供了一套完整的API以用于游戏开发,这使得游戏开发更为简单和快捷。
现在,我们探索一下MIDP 2.0在移动游戏开发环境中的使用。
三、 MIDP2.0在游戏开发中的地位
MIDP2.0 API是一组具有特别性能的API,可用于开发安全的,内容丰富的多媒体应用软件,包括适合于移动设备的游戏程序。MIDP 2.0基于以前的MIDP 1.0之上并提供一个更好的开发平台以创建高效快速的移动设备应用程序。
MIDP 2.0进一步提炼了MIDP 1.0的特性和有关功能。有关这些新特性的信息请参考What’s New in MIDP 2.0。新增添到MIDP上的重要特点之一是Game API,或更精确地说是javax.microedition.lcdui.game API包。通过该Game API,MIDP 2.0提供给游戏开发者现成的程序模块,这些模块在早期的MIDP 1.0时是你必须从头开始创建的。这些模块以类的形式提供,用于创建和控制各种游戏元素,如游戏画布、精灵、层等等(后文将介绍)。这样,MIDP 2.0大大减少了游戏开发者的创作时间。
进行游戏开发必需的另外两个MIDP 2.0 API包,在本文中也作了探索,它们是javax.microedition.midlet和javax.microedition.lcdui。
javax.microedition.midlet API包是开发各种类型的移动应用程序的基础。它包含javax.microedition.midlet.MIDlet类,它是所有的基于J2ME的移动应用软件(或称为midlet)的基类,它必须由所有移动应用程序的main类加以扩展后使用。非常类似于java.applet.Applet类,MIDlet类提供创建midlet程序的必要的资源。
javax.microedition.lcdui API包是开发各种类型的移动应用程序的用户接口所必需的。这个API提供类来创建和控制UI部件(例如屏幕,表单,文本框,单选按钮,等等)并且处理包括游戏在内的移动应用程序的输入。有使用AWT和SWING GUI开发经验的开发者会发现javax.microedition.lcdui包中的元素非常相似于这些API中的元素。
我将在本文的示例游戏开发期间讨论这些API中的和游戏开发相关的元素。
四、 构建示例游戏
为了更好地理解这些API和它们各自的类,你最好动手开发一个简单的移动游戏。这里是一个单人的离线游戏,通过障碍物线路的驾车游戏。玩家使用左键和右键用于改变车的方向到左边或者右边以防止与障碍物的碰撞。游戏在发生碰撞并显示得分后结束。该游戏命名为HardDrive。
注意:虽然这个示例游戏是使用J2ME Wireless Toolkit 2.1_01和J2SE 1.4.2_07 SDK在Windows 2000平台上开发的,但是,其它版本的与另外一些平台相匹配的Wireless Toolkit和J2SE SDK也可以利用。
现在开始构建游戏程序HardDrive。从前一节中得知,你第一个需要开发的程序是HardDriveMIDlet(HardDriveMIDlet.java),它扩展了javax.microedition.midlet.MIDlet类。
(一) HardDriveMIDlet.java
列表1.1:该代码片断来自于文件HardDriveMIDlet.java
import javax.microedition.midlet.MIDlet; import javax.microedition.lcdui.*; public class HardDriveMIDlet extends MIDlet implements CommandListener { ... ... ... ... ... ... ... ...
HardDriveMIDlet还实现了javax.microedition.lcdui.CommandListener接口来接收命令事件,它们是在应用程序执行和处理期间产生的。当发出EXIT,CANCEL,BACK,OK,STOP以及类似的命令-这些命令通过使用软按钮(在移动电话屏幕附近的特殊的按钮,除了箭头键以外)产生并被HardDriveMIDlet的commandAction()方法所处理-时,这些命令事件发生。为了提高效率,可把这些命令添加到画布上去。
HardDriveMIDlet用作所有canvas的容器,这些canvas是一些描述可用于在移动设备屏幕上进行绘制的对象。这里,midlet包含了HardDriveCanvas,它扩展了javax.microedition.lcdui.game.GameCanvas类。GameCanvas是一个专门的画布,用于为游戏程序绘制有效的动画图像,还能够查询为实现平滑动画效果而采取的脱屏图像缓冲技术有关的关键状态。
HardDriveMIDlet包含的另外的一个canvas是GameOverCanvas,它扩展了javax.microedition.lcdui.Canvas类。Canvas是一个简单canvas,用于绘制文本,线段以及简单的形状等。当需要在屏幕上进行简单的绘制时-例如为显示游戏初启画面,游戏结束屏幕以及游戏指令屏幕-这个canvas被扩展,而取代了繁重的绘制。一个游戏程序的midlet可以包括任何个数的canvas,但是每次仅显示一个canvas,这是通过使用javax.microedition.lcdui.Display类的setCurrent()方法来实现的。
HardDriveMIDlet还包含3个另外的重要方法,也称作lifecycle方法。它们是startApp()、pauseApp()和destroyApp(),分别相应于该midlet的Active,Paused和Destroyed状态。在HardDriveMIDlet的startApp()方法中,实现实例化HardDriveCanvas并通过使用HardDriveCanvas类的方法addCommand()把EXIT命令添加到它上面去。
(二) HardDriveCanvas.java
HardDriveCanvas实现了一个java.lang.Runnable接口来使它自己可以运行在自己的线程中,这对于独立地执行游戏循环是必需的。该游戏循环被连续不断地执行,直到终止游戏的必备条件满足为止(在本例中,当汽车碰撞到障碍物上或者在任何时候当玩家使用Exit按钮退出游戏)。
列表1.2:文件HardDriveCanvas.java中的游戏循环
public void start() { gameRunning = true; Thread gameThread = new Thread(this); gameThread.start(); } ... ... ... ... ... ... ... ... public void run() { Graphics g = getGraphics(); //... ... ...一些代码 while (gameRunning) //游戏循环 { tick(); input(); render(g); //... ... ...一些代码 try { Thread.sleep(timeStep ); //... ... ... ...一些代码 } catch (InterruptedException ie) { stop(); } }
列表1.2显示HardDriveCanvas.java中的游戏循环。这是一典型游戏循环,它包含了依次对tick(),input()和render()方法的调用。tick()方法检查是否停止该游戏的必需条件已经满足;如果满足,即相应地改变游戏的状态。方法input()处理游戏的键盘(keys assigned for游戏playing)输入并为每一次按键,如一个游戏元素的运动,执行必要的动作。根据其所处的状态,着色任务由render()方法来完成。
HardDriveCanvas也使用一个javax.microedition.lcdui.game.LayerManager的实例来增加和管理多层的HardDriveCanvas,其中每一层代表一个精灵。一个精灵是一部游戏中一个基本的可视化元素,或者是一个在游戏画布上移动的character,而且它能够与其它精灵(在这个示例中,汽车或障碍物都是精灵,它们可能进行彼此碰撞。)进行交互。每一个精灵形成一个虚拟层,它可能是全部或者部分透明地置于画布之上;这些层彼此以堆栈方式堆叠。一个精灵是一个javax.microedition.lcdui.game.Sprite类的对象,它负责显示、变形和旋转精灵以及进行精灵碰撞检测。被内部使用的tick()方法使用精灵类的collidesWith()方法进行碰撞检测。HardDriveCanvas实例化一个ObstacleManager类的对象,它用于着色并移动游戏画布上的障碍物精灵并检查是否它们与汽车精灵相碰撞。
(三) ObstacleManager.java
ObstacleManager负责创建和管理随机出现在汽车路径上的障碍物。为了简化和便利,ObstacleManager.java硬编码了每次出现在汽车路径上的障碍物的最大数目值。这个值可以根据需要进行修改。
列表1.3:该代码片段来自于ObstacleManager.java
private static final int MAX_OBS = 10; //... ...一些代码
为了在随机位置创建和显示障碍物,ObstacleManager使用了一种简单的策略。它产生最初的10个障碍物精灵,并使用LayerManager来把这些精灵添加到游戏画布上去。然后,它通过使用随机产生的x和y坐标值来设置它们的位置并开始朝着游戏画布的底部移动它们。一旦每一个障碍物到达了画布的底部而没有碰撞到汽车,它的位置就被通过使用相同的技术重新复位,而同时游戏的得分增加1。所以,ObstacleManager重用了同一个障碍物精灵并随机地显示它们。
(四) GameOverCanvas.java
GameOverCanvas是一个简单的canvas,它接收来自于HardDriveMIDlet游戏持续时间以及得分信息并显示之。
五、 准备示例游戏的发布
J2ME无线开发工具包提供了Ktoolbar-一个相当有用的工具-可自动化或半自动化处理有关编译,预先校验,打包及测试移动程序等一系列问题。
既然现在准备好了游戏代码,那么就应该把它们组织到由KToolbar提供的下面目录结构下(见Ktoolbar的用户指南-"Operating with KToolbar")。为此,启动KToolbar并创建一新工程HardDriveGame,它将包含HardDrive游戏程序,该程序位于J2ME无线开发工具包的安装文件夹下的apps子文件夹下。
HardDriveGame(定义用户的游戏工程名)
| ___src
| ___bin
| ___classes
| ___res
| ___lib
| ___tmpclasses
| ___tmplib
现在,只要简单地复制游戏程序的四个源代码文件到src文件夹下,把文件car.png和obstacle.png图标文件复制到res文件夹下。剩下的任何事情交由Ktoolbar处理好了。
接下去,下面操作将打开相应的HardDriveGame游戏工程,编译它(使用JDK编译器),并预校验该游戏程序。
选择"Open project"按钮,选择"HardDriveGame"->"Build"按钮,即可开始工程构建。
如果在工程创建过程中发生错误,相应信息会显示在KToolbar窗口中。你可以修改src文件夹下的游戏源代码来更改它们;但是,必须手工进行调试,因为Ktoolbar没有提供调试工具。否则,如果没有错误发生,将显示一条"构建完成"信息于KToolbar窗口上。
一旦游戏工程创建成功,你就可以在仿真器(一个KToolbar组件,它虚拟地模拟移动电话应用程序的执行)中运行以进行程序测试。
该游戏程序现在已开发完成,只等待发布了。为了使用KToolbar把游戏应用程序打包成一个.jar文件并进行发布,应执行下面的步骤:选择"Open project"按钮,选择"HardDriveGame"->"Project"菜单->"打包"->"Create package"/"Create obfuscated package"。
"Create package"菜单项将创建一标准.jar文件,而"Create Obfuscated Package"将创建一个更小些的而不是一个标准.jar文件。一旦打包完成,.jar文件的位置被显示在KToolbar窗口中;在打包期间还自动产生一个.jad(Java应用程序描述)文件,该文件在游戏程序运行期间为仿真器所用。
图1.1:运行示例游戏应用程序的模拟器
作为选择,在打包后,你可以对游戏程序的midlet施加签名,方法如下:
工程菜单->签名;这将为.jar文件创建一个数字签名并把它添加到.jad文件上。
现在,游戏应用程序的.jar和.jad文件,还有用KToolbar创建的MANIFEST.MF manifest文件,组合在一起成为一个midlet 套件,都准备好被发布了。
以上就是如何用Java进行2D移动游戏开发的整个过程。你可以根据本文提供的示例来构建你自己的游戏。