CSDN博客

img caifu2003

简约而不简单------浅谈手机游戏框架设计(转)

发表于2008/9/29 2:14:00  729人阅读

简约而不简单------浅谈手机游戏框架设计

游戏程序的主体框架在大中型游戏项目中是工程的躯干,在项目实施时游戏框架就集结了各个功能函数集群。作为游戏引擎的主体框架应当简约而不简单,用最少的代码,做尽可能多的事情。代码量少,表达规范,语法结构稳定的程序,这样整个框架才更容易维护。在程序设计这样一个充满艺术及哲学美的领域里,能用一句代码解决的问题,决不能写两句代码。简约而不简单,是每一个程序员追求的一种境界。

而在游戏框架基础上完成各个游戏功能模块开发后,则应专注代码的优化。时间和空间是程序设计的永恒的主题,程序设计过程就是对时间和空间的权衡和取舍。同时程序设计过程中应兼顾优雅和效率。

手机游戏框架规划流程为基础框架设定、功能模块实现、特色内容制作三个部分。在这三个部分中做到逻辑严谨,结构清晰。

基础框架设定

在确定一个游戏的框架(骨架程序)时,应该先了解一下运行平台的相关特性。

首先,这个框架应用于手机游戏平台。它的运行环境限制条件较多,且运行环境不尽相同。处理器无法做过多复杂运算,同时内存十分有限,一般采用动态内存进行内存分配。如果代码未经优化,势必会影响整个游戏的执行效率。运算效率和图形处理能力较弱,联网能力和带宽速度受限,屏幕显示区域有限,输入和输出能力有限。而从手机应用的角度来看,手机本身作为通讯工具,最基本的功能和特点就是通话和便携。

总结以上手机平台的特点,就决定了一个好的框架应该兼顾到这些最根本的问题:能够适应绝大多数的运行平台、提升代码执行的效率、易于程序员移植开发、适应突发状态(来电等)。当然,好的框架是需要通过多次的改进才能渐趋完善。

框架作为游戏的骨架程序,当仅有其骨骼代码时,也应该能够运行,并且对于后期加入的模块、函数都应该能够很好的支持,尤其是商业游戏框架。如同一张白纸,可以任由程序员在上面书写出不同类型的游戏。

当下较为普遍的框架结构如下(部分线程型)

 

而本文讲的,是另一种框架结构。(完全线程型)

从图中可以看出,两种框架的差别在于线程的布置。部分线程型框架通常让Canvas类实现Runable接口,使之可以作为一个线程来运行。完全线程型框架与前者的区别在于让MIDlet类实现Runable接口。将本身作为线程来运行,同时因为Canvas是由MIDlet来调用的,所以Canvas的运行也处于线程内。(见下面图解)

这样做的优点在于:将游戏线程独立于运行平台,利于运行资源的分配。同时,作为线程内的函数调用、内存堆栈等操作是安全且高效的。另外,当突发状态发生时(来电等情况),游戏作为线程在后台处于被挂起状态,比部分线程型的仅调用了PauseApp函数就束之高阁更有利于系统资源的调节,尤其在多任务操作系统中,如目前主流的Symbian60系统。

此框架以状态模式贯穿整个编写过程,乃至最后的特色内容制作。框架搭建初期,把游戏的状态分为开始、进行、结束三个状态。执行过程即游戏启动时,在开始状态搭建一个游戏线程,通过线程的启动,让游戏进入运行状态。当线程结束时,进入结束状态。此过程代码的实现在GameMIDlet

而进行状态又分为:Logo、菜单、游戏过程三个状态。例如:

处于GameMainGameCanvas类)中的GameLoop函数包含了游戏循环(While循环块),结束条件为Boolean类型变量bQuit为真。循环中执行绘图函数、逻辑更新函数和帧数控制。

绘图函数和逻辑更新函数判断当前游戏的进行状态(Logo、菜单或游戏过程)。根据不同的状态执行相应的代码块。(看下面图解)

以这样子的方法来构建整个游戏框架的话,不仅条理清晰,而且易于后期的开发,例如对于游戏进行状态的添加。例如在进行状态中加入“选项设定”状态。

本项目总共创建了如下类:

类名

功能

GameMIDlet

MDIlet类(线程接口),入口

GameMain

Canvas类,游戏框架

Logo

Logo状态开发商LogoSP Logo

Menu

菜单状态。

GamePlay

游戏运行状态

Role

精灵类,可生成主角、怪物、NPC等。

Map

地图类,承载了所有地图信息、关卡信息。

Sound

声音类(线程接口),用于声音播放。

 

功能模块实现

框架设定完毕后,根据框架的整体设计思想,进行框架代码的编写。编写过程中,以功能模块为单员组成各个函数集群。如按键处理集群包括了按键控制、键码转换等;绘图集群包括了背景绘制、地图绘制、角色绘制、图层绘制等;逻辑更新集群包括了数值更新、碰撞处理、动态贴图、图层管理等。

各集群之间不进行交叉操作,仅做数值(参数)传递。假设玩家按下了确定键,键值被捕获后,先交由按键处理函数工作。该函数先对键值进行解码转换(不同手机的键值可能不同,但是玩家只想作的确是相同的操作),由相应的按键处理函数(KeyPressed等)输出相应的值到逻辑更新集群中,例如:进入游戏。逻辑更新集群根据该命令,执行相应的更新函数,例如:把当前状态设定为游戏状态(GamePlay)。而绘图集群则根据游戏状态,执行相应的Render渲染函数。(看下面图解)

集群中也以状态模式来划分对应的函数调用。如:

private final void render() {

     switch(iGameState){

         case LOGO:

              logo.render();

              break;

         case MENU:

              menu.render();

              break;

         case PLAY:

              gamePlay.render();

              break;

         }flushGraphics();

}

整个函数根据状态值(iGameState)的不同,绘制相对应的画面到屏幕上。又如逻辑更新集群中的框架:

public final void update(long time_elapsed){

     switch(iType){

     case PLAYER:

         switch (iState) {

              case STAY:        break;

              case RUN:              break;}

         }

         break;

     case ENEMY:           

         switch(iState){

              case STAY:        break;

         case RUN:

              switch(iAIState){

              case CHASE:       break;

              case ESCAPE:      break;

              case MODE:        break;

              case ROAM:        break;}

              break;}

         break;

     case TREE:        break;}

     }

 

特色内容制作

将基础的各个功能模块添加完毕后,游戏应该处于可运行状态,并且对于任何一个状态的增删都不会影响其他的状态以及游戏的正常进行。完成这些工作后,游戏的开发真正进入了项目实施阶段。编程人员开始根据游戏的策划,填充相应的功能函数,并将函数加入到相应的集群中,完成“coder”的工作。

例如:游戏是一款横板卷轴游戏,对于精灵之间的碰撞检测函数就不同于斜45度俯视游戏,则添加或修改相应的碰撞函数。

或者:Boss对于主角的攻击(如子弹)会闪躲,普通怪物就不行。这样的话,就必须对于怪物精灵类的AI函数进行对于不同怪物类型(状态)的处理。

 

整个项目的框架建立是最重要的基础部分,如果框架搭建的合理且易于扩展,对后面的开发效率有很大的提升。同时,好的游戏框架不仅易于游戏的移植,甚至能够在其之上开发几种不同类型的游戏。功能模块的实现是决定游戏运行性能的关键,也是后期特色内容制作的扩展基础。同时完善清晰的功能模块可以让开发人员更好的进行项目规划与管理。

0 0

相关博文

我的热门文章

img
取 消
img