首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

3.4  小型入口:使用手持设备来接入MMP游戏世界

David Fox,Next Game

davidfox@ureach.com

玩家的角度来看,一流的MMP游戏通常都具有流畅的角色动画、大量的城镇、结构细致的建筑、富有层次的环境音效以及一些其他的虚拟现实特征。而最新的游戏机和PC硬件更是不断地把这一现实向前推进。

然而,正如任何一个文本界面MMP游戏的爱好者可以告诉你的,令玩家沉迷于MMP游戏世界的真正原因并不是它的视觉效果,而是它可以不受限制地访问另一个空间的能力。在21世纪初人们所拥有的技术中,最注重于使访问不受限制的莫过于移动电话和其他无线设备了。毕竟大多数人都会带着移动电话随处走动。支持无线设备的MMP游戏可以把玩家带入一个前所未有的游戏体验中。

在大多数MMP游戏中,即使在玩家退出游戏后,游戏世界仍然会持续运行下去。在玩家睡觉时,他们的角色和建筑可能会遭到攻击,游戏计划也可能会被破坏。不仅如此,当玩家离开游戏时,他们还可能会失去很多重要的社交机会。如果一个游戏可以在无线设备上运行,那么玩家几乎永远都不会退出游戏。至少在有重要事件发生时,玩家可以收到无线电子邮件或是短消息(Short Message Service,SMS)。有些游戏甚至允许玩家发出一些简单的高级指令,譬如说“让所有部队都进入防御状态”。

理想情况下,一个真正的移动游戏不仅应该允许玩家使用手持设备来接入游戏世界,还应该让他们可以做到任何在台式机上能够做到的事情。如果某个玩家的部队在他参加业务会议时遭到偷袭,他应该可以立即收到通知并且暗自登录游戏和敌人作战。

3.4.1  无线设备和网络

虽然无线设备的功能和速度正在飞速地提高,它们仍然具有很多缺陷。大多数无线设备的屏幕是黑白的,并且长和宽都只有大约100个像素;处理器的速度比台式机慢100倍;而内存更是小得可怜(以K而不是M来计量)。

不仅如此,大多数第二代(2G)无线网络的传输速度只有9.6kbit/s。

大多数欧洲移动电话都是基于GSM(Global System for Mobile Communication)的,它们发送数据的速度是9.6kbit/s。有些网络使用时分多址(Time Division Multiple Access,TDMA),和GSM一样,它也受到9.6kbit/s的限制。北美和南美、前苏联、以色列、东亚和中非的网络基于码分多址(Code Division Multiple Access,CDMA)来传输数据,它的速度略微高一些,可以达到14.4kbit/s。虽然2.5G和3G网络逐渐开始产业化,但是要让大多数用户使用上它们还需要很多年的时间。

更糟糕的是,由于无线电通讯固有的干扰和噪声,广域无线网络通常都具有很大的延迟。大多数无线网络需要让数据包通过很多路由器。通常基于卫星的无线网络会导致更大的延迟。在日常使用中,1到2秒的网络延迟并不少见。

虽然这些设备和网络受到诸多限制,但它们依旧非常流行。某组织预测到2005年底,全球使用移动无线设备访问因特网的用户将达到7.29亿人,而在2000年底,这个数字还只有3900万[Intermarket01]。

MMP游戏开发人员所面临的问题是,怎样才能用这些高延迟、低带宽并且CPU也不强的设备来让玩家忘我地投入到游戏世界中去呢?首先,开发人员有必要知道编写无线游戏所使用的语言以及它们的优缺点。

3.4.2  J2ME

Java是由太阳微电子公司(Sun Microsystems)创造的,它已经成为无线设备开发的标准语言。这是一个开放的语言,所有必须的开发工具都是免费提供的。

Java运行在虚拟机上,这意味着只要开发人员使用正确的方法,理论上相同的字节码就可以在任何支持Java的平台上运行。Java被设计得非常易于使用。作为一种面向对象语言,它不支持显式的指针,也没有复杂的内存操作,通过自动垃圾收集来管理内存。系统事件(譬如说,在进行游戏时接到一个语音呼叫)会被自动处理。最重要的是,Java小应用程序(applet)不能访问安全运行环境以外的任何函数和内存,这意味着几乎不可能用它编写出恶意的代码或病毒。

J2ME(Java 2 Micro Edition)[J2ME01]在试图保持标准Java语言的优点的同时,对其进行了精简以适应小型设备上的开发,譬如说行动电话、寻呼机和掌上电脑。几乎所有主流移动电话生产商都参加了Sun制订CLDC(Connected,Limited Device Configuration)[CLDC01]和MIDP(Mobile Information Device Profile)[MIDP01]的过程。一个为移动电话编写的Java小应用程序被称为“移动应用程序(MIDlet)”。

很多设备生产商发布了J2ME的扩展API。譬如说,西门子(Siemens)以MIDP为基础开发了一套游戏API。NTT DoCoMo并没有使用MIDP,它使用的是一个独立的Java实现,被称为I-Appli。

目前,MIDP 1.0还有一些限制:它不支持透明图形和浮点运算;它不能通过本地代码(native code)直接访问设备硬件、文件I/O或是内存。HTTP是MIDP设备必须支持的惟一协议。通常所有MIDP游戏都是根据HTTP来设计的,因为这是所有MIDP设备都必须支持的最低标准。

MIDP 2.0是为更强大的设备设计的。它对上述缺点中的大多数进行了修正和改进。

3.4.3  BREW(二进制的无线运行时环境)

Qualcomm开发了一套虚拟机和语言,称为BREW(Binary Run-Time Environment for Wireless)[BREW01]。这是一个以C++为基础的开放性语言。Qualcomm已经把BREW植入到了很多CDMA手机的芯片中。BREW也可以支持其他语言,目前Quallcomm正和IBM合作在BREW上创建一个Java虚拟机。

BREW没有安全运行环境,这意味着应用程序可以直接访问文件系统、网络套接字、内存和屏幕。它还支持透明的精灵(sprite),并且有一个内建的资源文件系统以方便开发人员载入图片和声音。

不仅如此,BREW发行系统(BREW Distribution System,BDS)还为在线购买应用程序并直接下载到移动设备提供了一个标准方法。这个集中支付系统对开发人员和最终用户来说都很方便。

BREW的缺点在于,它的当前版本只支持500字节的动态内存,并且不支持任何静态数据。要开发面向最终用户的BREW应用程序,开发人员必须购买非常昂贵的ARM编译器。目前支持BREW的移动电话也很贵,并且内存非常有限。此外,对一个运行在真实手机上的BREW程序进行调试也是非常困难的。

因为今后大多数设备会支持J2ME,并且在BREW上也可以进行Java开发,本文中的例子将使用Java。然而,这里的概念可以用任何语言实现。

3.4.4  无线界面和游戏设计总览

把一个精彩纷呈的虚拟现实移植到小型设备中,需要开发人员对现实做一些本质上的改变。每个游戏环境都是由人物、地点和物品等组成的。玩家和这个环境进行交互的方式称为“游戏模式(gameplay)”。移植时,设计人员必须同时改变游戏环境和游戏模式。

大多数游戏的核心是人物或角色。游戏通常围绕一个主角,并且主角通常会和某个敌人进行战斗。为了使游戏中丰富的角色即使在移动设备上也能栩栩如生,设计人员必须把它们浓缩为精华。很明显,游戏设计人员必须去掉所有漂亮的三维模型以及那些复杂的统计信息。必须使用精灵(sprite)来表示人物,动画的帧之间只能改变很少的像素,就好像处于黄金时代的家用游戏那样。就算是劳拉·克劳伏特(《古墓丽影》的女主角)看上去也只能和大嘴巴(PacMan)一样。

游戏中的地点是所有游戏行动发生的地方。通常二维地图就可以对三维空间进行充分地表示。游戏设计人员可能需要实现战场雾化(fog-of-war)或是运用其他技巧来避免让某些玩家获得战术上的优势。不仅如此,他们还必须对复杂的物理运算以及其他环境交互进行大量的简化。游戏设计人员最好把游戏环境中最有趣的特性提取出来,然后在移动设备上对这些部分进行模拟。

设计人员必须对很多东西进行修改以使得它们适合二维环境,这包括武器、财宝、钥匙、以及角色在游戏中可以穿过的门。那些在显示器和电视上看上去很真实的东西,在小屏幕上只能是抽象的。我们必须把所有物品都缩减为图示、图表或其他简化的表达。

最后,也是最难实现的,就是对游戏模式自身的改变。移动电话通常只能通过几个方向键来进行输入。并且,因为延迟很大,任何依赖于迅速反应的游戏模式都必须改变。本质上,必须把游戏的一部分做成回合制的。这种模式转变类似于教练和四分卫之间的关系。这里,玩家就是教练,他通过发送指令来指挥球的运行,而不是像四分卫那样直接发出命令来让球移动到(x,y)位置。

表3-3中所包含的例子说明了在移动设备上可以怎样表示游戏机游戏或是PC游戏中的主要特性。

表3-3                                        游戏特性:从大到小

游戏机/PC

手持设备

户外

在旷野中有很多城镇、自然资源和废墟

好像旅游地图,使用图标来表示特殊位置或特殊特性

城市街道

3维或等容(isometric)的迷宫

垂直卷轴迷宫

户内

使用走廊分隔的房间,有锁住的门、自动扶梯和垂直电梯等

好像建筑蓝图,使用图标来表示锁、楼梯等

过场

动画

静态的图片和一些文本

其他角色

使用动画表示

地图上的图标

角色状态

带有图形的数据表

记分牌

背囊

支持拖曳的图形界面

带有复选框(checkbox)的列表

角色互动

非常精确,使用特殊的用户界面以及特殊的动画

使用文本或是图标

大型战斗

动画,鸟瞰

文本描写

战略

即时

使用分支图(branching diagram)预先计划,可以进行更新

战术

不停的输入,迅速切换武器、魔法和模式

使用具有教练功能的AI代理

购物

在商场中游荡,从货架上购物

层次菜单

听觉

音箱、耳机或是像漫画书一样的气球提示窗口

滚动信息

交谈

话筒或是打字

预先定义的消息

要记住的关键是,虽然在移动设备上具有完全不同的游戏经历,但真实的游戏世界并不需要被改变。虽然游戏设计人员不能使用第一人称视角来设计游戏,就好像一个正在法国北部村庄中战火纷飞的街道上奔跑的士兵那样,但可以使用一个将军的视野,使用一个基于计算机的卫星视角来控制特定士兵的行进。

3.4.5  对象设计

由于同一个对象在不同的无线设备和桌面版本中表现方式会完全不同,游戏必须使用一个可高度扩展的架构。设计人员必须对每个人物、地点和物品进行重新设计以支持各种不同的输入设备和不同的细节层次。虽然每个对象的关键属性(譬如说它在游戏世界中的位置和它的生命值)将保持一致,但是输入/输出方法和对象的显示必须非常灵活。

游戏的设计需要克服两个主要问题:向每个平台发送合适的对象和事件;对用户输入进行处理。要做到这两点,关键在于让游戏中的每一个数据类型都可以根据具体情况进行定制和伸缩。这一设计方法不仅可以帮助开发人员把游戏延伸到无线设备上,还可以提高游戏在不同的平台和网络类型上的总体性能。

1.发送对象

假设在一个虚拟的客栈中,有一个移动用户的角色和一个桌面用户的角色站在一起。每个玩家都需要接收同样类型的信息:周围的建筑、角色和物体。但是发送给每个客户的实际内容可能有着巨大的差别。

现存的标准可以用来参考以构思怎样创建这样一个系统。对于Web应用程序来说,使用XSLT(Extensible Stylesheet Language Transformation)[XSLT01]模版语言就可以对同样的XML数据为不同类型的客户进行转换。譬如说,同样的内容可以被格式化为Web浏览器可以理解的HTML,也可以被格式化为无线设备可以理解的WML(Wireless Markup Language),或是被格式化为电话设备可以理解的VoiceXML。如图3-7所示。

图3-7  XSLT是怎样工作的

XSLT可以帮助游戏开发人员把数据的逻辑结构和表示分离开。设计人员可以在游戏中使用类似的设计方法。譬如说,角色的数据可以使用图3-8中的基类表示。

图3-8  基本的角色(Character)类

假设这个类中的每一个属性都有它自己独立的类。这使得每个属性都可以执行一些特殊的功能,并且可以有父属性和子属性。这个角色(Character)类可以使用下面的XML表示。

<CHARACTER>

    <HITPOINTS>100</HITPOINTS>

    <NAME>Bartender</NAME>

    <DESCRIPTION>This swarthy character can serve you a fine mug of ale!</DESCRIPTION>

    <LOCATION><X>100</X><Y>320</Y><Z>99</Z></LOCATION>

    <SPEED><X>23</X><Y>0</Y><Z>0</Z></SPEED>

    <DIRECTION><X>1</X><Y>0</Y><Z>0</Z></DIRECTION>

    <STATE>pouring</STATE>

</CHARACTER>

作为一个被简化了的例子,服务端可能希望把上面所有的数据发送给一个游戏机玩家,但是只发送如下某些数据给无线玩家。

—   只发送战斗(FIGHTING)或是死亡(DEAD)状态,并且把状态简化为“F”和“D”。

—   只发送X坐标和Y坐标的更新,不发送速度和方向。

—   不发送描述(description)。

也就是说,服务端只会发送下面的XML数据。

<CHARACTER>

    <HITPOINTS>100</HITPOINTS>

    <NAME>Bartender</NAME>

    <LOCATION><X>100</X><Y>320</Y></LOCATION>

</CHARACTER>

通过DeviceSender接口,游戏管理人员可以为每个属性设定规则,并且在运行时使用一种类似于XSLT的方式对它们进行转换。基本上,每种数据类型都需要实现DeviceSender接口。图3-9中是这个接口的类图。

图3-9  DeviceSender接口

sendToDevice(向设备发送)方法要返回一个字符串、字节数组、字符指针或是任何可以用来创建网络消息的数据类型。用来保存每个角色状态信息的状态(State)类可能会有如下这样一个方法。

public String sendToDevice(Device d)

{

    if (d instanceof Wireless)

    {

        if (thestate = State.FIGHTING)

            return "F";

        if (thestate = State.DEAD)

            return "D";

        else

            return null;

    }

    return thestate.toString();

}

每当服务端向一个客户发送数据或事件时,只需要调用每个数据的sendToDevice方法就可以了。

2.接收输入

现在,假设这个移动用户决定和桌面用户进行一场战斗。服务端不仅需要向移动用户更新战斗情况(可能是文本方式的),还需要让他可以发送高级的“指导”命令,譬如说通过在嵌套菜单中进行选择来发出这些命令。

与此同时,这个桌面用户可能正一边看着两个3D角色在进行搏斗,一边疯狂地摇动着他的游戏手柄。在所有条件相同的情况下,由于桌面玩家能够更快地对意外情况作出反应,因此相对而言他更占优势。但是,如果AI设计得很好,客观端就可以给移动用户一些战斗机会。一个由移动用户控制的高级角色应该能够战胜一个由桌面用户控制的低级角色。

大多数MMP游戏都有一个仿真对象(Simulation Object,SOB)基类,所有的角色、地点和对象都是从它继承而来的[GPG01]。这些SOB之间的关系使得服务端可以为游戏世界维护一个巨细无遗的仿真。根据具体实现的不同,SOB可以被保存在数据库、内存或是XML中。

在客户端,这些SOB将会是特殊的代理对象。譬如说,行动代理(ActorProxy)类可以实现两个主要的方法:ReceiveEvent(接收事件)会处理来自服务端的事件,RequestAction(请求行动)会告诉服务端试图进行一个给定的行动。

从服务端发出的(由客户端的ReceiveEvent方法接收的)事件也应该实现DeviceSender接口。这样服务端就可以根据不同的目标平台以不同的方式传输同一个事件。

对于游戏机平台和无线设备来说,客户端的RequestAction方法将有很大的差别。服务端必须能够对接收到的事件进行合适的转换。每当服务端接收到一个事件,它必须把发送这个请求的设备作为一个参数传递给一个从事件处理器(EventHandler)抽象类派生出来的类,如图3-10所示。

游戏开发人员应当为游戏支持的每个设备创建一个独立的事件处理器类。譬如说,一个无线事件处理器(WirelessEventHandler)可以把无线设备发送的事件转换为较大的游戏事件。事件处理器还可以和主要的游戏仿真对象相关联以确定如何处理事件。譬如说,一个由无线设备发出的事件可能过了很长时间才到达服务端以至于该事件已经失效了,这时事件处理器可以把它忽略掉。

图3-10  事件处理器抽象类

3.加入智能

大多数游戏只把人工智能应用在非玩家角色上。为了创建一个即使在用户输入很少的情况下都可以持续运行的游戏世界,本文建议让每个角色都能与一个很强的AI控制状态相关联。这样游戏开发人员就可以使用游戏中最复杂的AI机制去控制每个角色以及游戏中的其他对象。

图3-11中是AI控制管理器(AIControlManager)类的类图,它保存了指向所有控制状态(ControlState)类的连接。当需要进行一个行动时,它会根据当时的情况选取一个合适的控制状态类。每个角色都应该有它自己的AI控制管理器。这样,同一个角色就可以在多种状态(譬如说完全由系统控制;偶尔受到提示;完全由用户控制)之间进行切换。因为AI的运算量很大,所以游戏控制人员甚至可以根据服务器的当前性能来调整AI控制的级别。

图3-11  AI控制管理器类

控制状态(controlStates)数组具有给定角色可以使用的每一个控制状态的指针。AI控制管理器中的PerformAction(执行动作)方法会检查是否锁定了某个控制状态,如果锁定了,它会调用那个类的PerformAction方法。如果当前没有锁定任何控制状态,缺省控制状态的PerformAction方法将会被调用。

譬如说,如果一个无线用户觉得他可能会遭到一次偷袭,他会要求一条特定的巡逻犬在接下去的10分钟内负责警戒。服务器应该把用户控制状态(UserControlState)设为当前活动的控制器,它会执行用户的警戒请求。用户控制状态会持续锁定10分钟,除非用户发出另一个请求。一旦时间过去,用户控制状态就会解除锁定,于是AI(缺省控制状态)就会重新获得控制。

服务器不仅可以根据时间来进行用户控制状态锁定,还可以根据优先级来进行锁定。服务器还需要确保对ReleaseLock(解除锁定)方法进行适时的调用。譬如说,如果巡逻犬将会持续警戒10分钟,除非它快要死亡,那么当它接近死亡时,用户控制状态就会解除锁定,这样AI控制状态就会接管并尝试挽救它。

3.4.6  网络设计:使用代理服务器

每当有相关事件发生,服务端都会向客户端发送简单的更新。问题在于,服务端怎样才能确定对于不同客户而言,哪些事件是相关的呢?通常,客户端会持续运行一个本地的游戏仿真并且可以告诉服务端它所需要的信息。然而,由于无线设备的内存极其有限,即使要在客户端保持一个游戏仿真的近似也是不可行的,更不用说在客户端保持整个游戏仿真了。

服务端可以通过一个代理服务来模拟客户的视角并且只向小型设备发送那些最重要的信息。不仅如此,对很多移动电话(特别是那些使用MIDP的)来说,HTTP是它们惟一可以使用的通讯协议。游戏开发人员当然不希望把所有的游戏数据包都通过HTTP传输。相反,他们希望可以用任何协议来编写游戏服务端。代理服务器会负责转换并且把相关信息用HTTP协议来打包。

当然,代理服务器会带来额外的延迟。但是它可以为那些支持更好的网络协议的设备创建更好的游戏体验。譬如说,代理服务器可以通过调整所要发送的数据的内容和频率,来对不同设备进行智能化的处理。

3.4.7  总结

要把一个内容丰富的图形化多人世界装入一个小型设备,工作人员必须作出大量的牺牲和妥协。游戏开发人员不仅需要支持两套客户代码,还需要进行主动的设计、测试和调整来确保游戏既富有趣味又能够在所有平台上都保持平衡。只需要在设计时多加考虑,就可以让每个最新的游戏特性都可以被不同的设备访问。这可以让玩家在旅途中、在工作时、在上课时或是在住所附近闲逛时都可以投入到游戏世界中。让玩家更方便地进入游戏世界有助于创建一个更加投入的玩家社区,最终可以消除游戏和现实之间的界限。

3.4.8  参考文献

[BREW01] Qualcomm.com,BREW home page,http://www.qualcomm.com/brew/.

[CLDC01] Sun.com,“CLDC Information Page,” http://java.sun.com/ products/cldc/.

[ALEX02] Alexander,Thor,“A Flexible Simulation Architecture for Massively Multiplayer Games,” Game Programming Gems 3Charles River Media,2002.

[Intermarket01] The Intermarket Group,“Mobile Wireless Internet Briefing,” 2001.

[J2ME01] Sun.com,J2ME information page,http://java.sun.com/j2me/.

[MIDP01] Sun.com,“MIDP Information Page,” http://java.sun.com/ products/midp/.

[XSL01] W3.org,“The Extensible Stylesheet Language (XSL),” http://www.w3.org/Style/XSL/.

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论