from: http://blog.csdn.net/popy007/article/details/8301133
一个基于组合模式的游戏地图系统
地图系统
地图系统是游戏开发永恒不变的一个主题。在大多数游戏开发中,我们都需要和地图打交道。不同的游戏可能采用不同的地图系统,比如对于2D游戏来说,可能的地图类型包括:
1)Rectangular tile,即矩形tile。
2)Isometric,即等测地图。
3)Hexagonal tile,即六边形tile。
等等。
而对于3D游戏来说,一般包括两种主要类型:
1)基于3D空间的2D地图
2)完全3D空间地图
对于第一种类型,实际上是2D地图系统的一种3D推广,游戏中的地图还是在一个2D平面上,但是在3D空间的一个平面上。场景中的游戏对象可以都是3D模型。但地图本身仍然通过2D地图的方式进行处理。
第二种一般在3D图形学中叫做场景管理(Scene Management)。这是对真3D场景的一种处理方式:地图信息不再处于某个平面上,而是具有任意的3D几何信息。对于处理这种非规则的3D几何地图系统,我们一般采用分类的方式进行单独处理,比如:
1)室外地形系统
2)室内地图系统
3)基于portal的系统
等等。针对不同的类型,3D场景系统一般采用不同的管理方法,比如quadtree、octree、bsp、portal等等场景管理方式。可以说这个领域很广泛、也很复杂。
我们当然不可能具体地讨论所有这些地图系统。那么我们讨论什么呢?我们将讨论一种思想,这种思想贯穿于所有的这些地图管理方法之中,以提供一种健壮、合理、便利的代码结构。而这种结构不论是在游戏产品还是在开发工具中,都扮演着举足轻重的作用。这就是层次体结构。
层次体结构
对于复杂的问题以及结构,我们都倾向于一种称为“分治法”的方式进行处理。层次体结构实际上就是一种分治法,它通过一种树形结构来表示“整体-部分”的层次概念。基于这种方法,开发者可以很容易地对系统进行不同等级的灵活控制,同时获得一种复用性优势。
我们来举一个简单例子,来让大家更好地理解这些抽象概念。对于最简单的2D矩形tile引擎来说,开发者们经常会把场景分成多个层(layer)和一个根(root),如下图所示:
这就是一个最简单的层次体结构。它表明了一种整体和局部的从属关系:root可以看作这个地图本身,它代表整体。而它的子结点,则看作是这个地图的每个层,他们代表局部,属于整体。我们再具体一点,假设我们把地图分成了3层:
Layer 1 - 地面层
Layer 2 - 中间层
Layer 3 - 天空层
地 面层是永远处于”最下面“的层,地图上的任何东西都会处于它的上面,这一层包括普通土地、草坪、沙土地、公路等类型的tile。中间层就是地图上的对象 层,它永远处于地面层之上,这一层包括:房子、树木、玩家角色、NPC等活动对象,这些对象之间的位置关系会随时变化,因此互相遮挡的关系也会变化,需要 实时进行排序。天空层包括天上飞的鸟、飘浮的云朵等对象,它们永远处于地面层之上。
更进一步地,我们可以在每个layer上再增加子layer——这可以根据具体游戏对象的类型,比如把所有沙土地对象,都放到一个layer上,当玩家走到上面的时候,会减慢速度。如下图所示:
如我们所看到的,对这些对象进行3个layer分类,我们获得了很多好处:
1)分区渲染-渲染的顺序可以通过layer自然的处理:地面、中间、天空,这样的顺序保证了渲染结果的可视关系的正确。
2)分区更新-只有中间层的对象需要实时排序,这避免了对无需排序对象进行排序的无效计算。另外,可以直接用沙土层和玩家做碰撞检测——避免了不必要的计算。
3)总体控制-在对地图进行编辑的时候,我们可以非常方便地显示、隐藏、移动、删除不同的层。被操作的每个层上的对象都得到统一的处理。
而 这些好处也不仅仅局限于矩形2D tile地图,任何地图系统都可以从中得到这样的好处。比如在3D的场景管理中,quadtree、octree、bsp本身就是一种层次体结构。它们通 过树形结构对场景进行划分,从而以一定的规则将场景中的多边形安排到树中。另外,对于3D的所谓保留模式(Retained Mode)渲染,实际上就是通过把场景安排成一颗场景树来进行处理。系统一般会提供一个类似这样的接口:
void GraphicsEngine::render( SceneNode& sceneTreeRoot );
sceneTreeRoot就是场景树的根结点,从该结点向下就可以遍历整个树形结构,并进行任何你希望的操作——这当然以渲染为主。
在一些支持保留模式渲染的引擎中,一般设计师或美工会通过一些所见即所得的工具进行场景编辑,放置模型,虚拟物体,架设相机等等。最后导出一个文件,供引擎使用。而导出的往往就是一颗场景树,连相机都会作为一个结点存在于该结构中。
复用性
层 次体结构的另一个巨大优势在于复用性,而这往往体现在设计和实现两个层面上。想象我们在地图里面将几块石头摆放成了一种特殊形状,这种形状暗示了某种游戏 中的宗教意义。而根据设计需求,该形状可能会摆在地图中的很多位置。由于整个地图通过组合模式被建立成了一棵场景树,我们则可以把这个形状的几个石头,单 独的做成一个子layer。然后在不同的地方(结点)放置这些子layer。而在代码级别上,这些layer中的石头实际上是通过类对象指针保存的,因此 存放开销完全可以接受。所以,我们每次给一个结点增加一个这样的layer,就添加了这些石头所组成的一个形状——我们实际上是通过一种组合的方式进行特 定结构的复用。请注意,这些复用是可以嵌套的!这意味着你可以用这些子layer再组合更复杂的层,然后服用这些更复杂的layer。这种复用带来的威力 是巨大的,在两方面提供优势:
1)设计开销 -通过定义一个子layer,我们可以反复使用该layer,还可以嵌套!
2)内存开销 -只通过指针存储对象,实际对象内存只有一份。
这种复用性带来的利益驱使我们开发了一套2D动画系统——用场景树的方式组织动画。允许对不同复杂组件(可以看作这里的layer)的嵌套。以后如果条件允许,我会写一篇关于该系统的文章,帮助一下初学游戏开发的朋友理解2D动画系统。
层次体的简单实现
层次体结构实际上是一种组合(Composite)模式。根据GoF的著作《设计模式》所描述:组合模式通过一种树形结构来体现一种“整体和部分”的观念,从而让处理单一对象和对象聚合存在一种统一的形式。下图所示即组合模式:
Leaf 是单一对象,composite是组合对象,也就是一个对象聚合体。它们都继承自component类,拥有相同的操作方式Operation——这是关 键,也是组合模式的核心思想:在客户(client)看来,操作一个leaf和一个composite没什么区别,都调用它的Operation,但 composite是个聚合体,它会在自己的Operation中调用每一个聚合对象的Operation。
这里单一对象就可以理解为地图中的一个具体对象(树木、房子、NPC等等),而组合对象则可以看成是地图的一个layer——它聚合其它对象(树木、房子、NPC,或者是另一个layer)。
下面我们实现一个简单的层次体结构,从代码级别来深入认识该系统:
class MapNode { public: virtual ~MapNode() {} virtual void cycle() = 0; virtual void draw( GraphicsContext& g ) = 0; }; class Node_Layer : public MapNode { public: void addChild( SceneNode* child ) { m_children.push_back( child ); } void removeChild( SceneNode* child ) { for( std::vector< SceneNode* >::iterator it = m_children.begin(); it != m_children.end(); ++it ) { if( *it == child ) { m_children.erase( it ); break; } } } virtual void cycle() { for( int i = 0; i < m_children.size(); ++i ) { m_children[i]->cycle(); } } virtual void draw( GraphicsContext& g ) { for( int i = 0; i < m_children.size(); ++i ) { m_children[i]->draw( g ); } } protected: std::vector< SceneNode* > m_children; }; class Node_Tree : public MapNode { public: virtual void cycle() { Update the state of the tree... } virtual void draw( GraphicsContext& g ) { Draw the tree via g... } };
以上是一个非常简单的组合代码结构。 MapNode是地图结点基类,我们用它的指针或引用来操作整个系统。它提供两个抽象方法
void MapNode::cycle
void MapNode::draw
分 别用来进行帧更新和渲染,具体实现由子类决定。Node_Layer就是地图层类,它就是所谓的聚合体。Node_Tree是一个单一对象,它表示地图上 的树这种对象。可以看到它们对具体操作的实现清晰地表达了整体-部分的思路:Node_Layer把操作分散到各个子对象中,而Node_Tree则是老 老实实作自己的事情。这便是一个最简单的层次体结构实现。一个简单的游戏和可能会如此使用上述代码:
class Node_Root : public Node_Layer {}; class Node_Player : public MapNode { public: virtual void cycle() { Update the state of the player... } virtual void draw( GraphicsContext& g ) { Draw the player via g... } }; Node_Root root; Node_Player player; Node_Tree tree; root.addChild( &player ); root.addChild( &tree ); for(;;) { root.cycle(); root.draw( g ); }
我们建立了一个root类作为世界的根结点。然后生成了一个玩家和一棵树,都放进了场景里,接着进入了我们的游戏循环。还有比这更简单的么?
以该结构作为一个开始,开发者可以进行扩展。包括加入MapNode的共性成员:
位置
可见性标志
等等。对于非聚合类型的MapNode子类的设计,那就和你的游戏相关了。比如对于Node_Player来说,可以增加移动控制、生命、动画等等。这里提供的只是一种设计上的思路,而经过开发者的细节设计和扩展,该系统将发挥实际功效。
总结
上 面我们介绍了层次体概念以及该结构的简单实现。它是一种优秀的地图系统、场景管理方法。不论是在2D还是3D中,都可以发挥巨大的威力。不论对于游戏开发 初学者还是专家,在实际的游戏代码中你都会看到它的影子。因此,独立地考察和分析该系统对于开发者来说都是有很必要的。
相关推荐
组合模式:用组合模式显示其所选商品信息,并计算所选商品总价的功能。说明:假如王同学到万达生活用品店购物。用 1 个红色小袋子装了 2 包衡阳特产(单价 25 元)、1 张衡阳地图(单价5.8元).....5.享元模式:在...
Sqlite 一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中 W3C 万维网联盟,创建于1994年,是Web技术领域最具权威和影响力的国际中立性技术标准机构。主要的工作是发展 Web 规范,...
海洋CMS 影视管理系统,海洋影视管理系统(seacms,海洋cms)是一套专为不同需求的站长而设计的视频点播系统,灵活,方便,人性化设计简单易用是最大的特色,是快速架设视频网站首选,只需5分钟即可建立一个海量的...
关键字( Primary Key ): 表中的一个属性或几个属性的组合、其值能唯一地标识关系中的一个元组。关键字属性不能取空值。 . 外部关键字(Forgien Key): 在一个关系中含有的与另一个关系的关键字相对应的属性组称为该...
海洋影视管理系统(seacms,海洋cms)是一套专为不同需求的站长而设计的视频点播系统,灵活,方便,人性化设计简单易用是最大的特色,是快速架设视频网站首选,只需5分钟即可建立一个海量的视频讯息的行业网站。...
海洋影视管理系统(seacms,海洋cms)是一套专为不同需求的站长而设计的视频点播系统,灵活,方便,人性化设计简单易用是最大的特色,是快速架设视频网站首选,只需5分钟即可建立一个海量的视频讯息的行业网站。...
3.4 案例二:Monopoly游戏系统 第二部分 初 始 阶 段 第4章 初始不是需求阶段 4.1 什么是初始 4.2 初始阶段的持续时间 4.3 初始阶段会创建的制品 4.4 何时知道自己并不了解初始阶段 4.5 初始阶段中有多少UML...
3.4 案例二:Monopoly游戏系统 第二部分 初 始 阶 段 第4章 初始不是需求阶段 4.1 什么是初始 4.2 初始阶段的持续时间 4.3 初始阶段会创建的制品 4.4 何时知道自己并不了解初始阶段 4.5 初始阶段中有多少UML...
插件开发是一个系统必不可少的部分,一个很好的插件机制是非常重要的,TinyShop的插件开发设计的特别的简单易用,可以是只是视图的Widget,也可以是功能强大的逻辑处理,同样也可以是两都的完善结合,插件的设计在...
海洋影视管理系统(seacms,海洋cms)是一套专为不同需求的站长而设计的视频点播系统,灵活,方便,人性化设计简单易用是最大的特色,是快速架设视频网站首选,只需5分钟即可建立一个海量的视频讯息的行业网站。...
海洋影视管理系统(seacms,海洋cms)是一套专为不同需求的站长而设计的视频点播系统,灵活,方便,人性化设计简单易用是最大的特色,是快速架设视频网站首选,只需5分钟即可建立一个海量的视频讯息的行业网站。...
海洋影视管理系统(seacms,海洋cms)是一套专为不同需求的站长而设计的视频点播系统,灵活,方便,人性化设计简单易用是最大的特色,是快速架设视频网站首选,只需5分钟即可建立一个海量的视频讯息的行业网站。...
DbSite企业网站管理系统采用.Net构架,根据需求可配置多种数据库,全站基于SEO核心开发,界面与数据完全分离,内置多个常用网站模块:企业基础信息模块,新闻资讯模块,产品模块,在线留言模块,下载模块,招聘模块...
本系统采用ASP FSO ACESS,建站成本低廉、快速,可以快速建立一个界面好、功能强、安全性高的中小型WEB站点。 3、功能强大: 本系统定位于中小型ASP网站程序,前后台操作方便,功能强大。 4、个性设置: 本系统...
诚和道微电影CMS程序是基于织梦开发的一套HTML5自适应微电影程序,风格基本跟"V电影"相似,功能可以满足想要做一个大型微电影网站的用户需求。 诚和道科技为符合SEO要求开发大量功能,比如百度结构化数据生成,搜索...
海洋影视管理系统(seacms,海洋cms)是一套专为不同需求的站长而设计的视频点播系统,灵活,方便,人性化设计简单易用是最大的特色,是快速架设视频网站首选,只需5分钟即可建立一个海量的视频讯息的行业网站。...
站主来说是B2B网站,对于会员来说相当于一个B2C模式,结合在线支付工具,会员 可以自主开设商铺,实现产品在线销售与订购,如淘宝类的购物一样, 拥有完整的产品 在线交易流程. 在线销售 完整的多用户商城...
3.4 案例二:Monopoly游戏系统 第二部分 初 始 阶 段 第4章 初始不是需求阶段 4.1 什么是初始 4.2 初始阶段的持续时间 4.3 初始阶段会创建的制品 4.4 何时知道自己并不了解初始阶段 4.5 初始阶段中有多少UML...
3.4 案例二:Monopoly游戏系统 第二部分 初 始 阶 段 第4章 初始不是需求阶段 4.1 什么是初始 4.2 初始阶段的持续时间 4.3 初始阶段会创建的制品 4.4 何时知道自己并不了解初始阶段 4.5 初始阶段中有多少UML...
3.4 案例二:Monopoly游戏系统 第二部分 初 始 阶 段 第4章 初始不是需求阶段 4.1 什么是初始 4.2 初始阶段的持续时间 4.3 初始阶段会创建的制品 4.4 何时知道自己并不了解初始阶段 4.5 初始阶段中有多少UML...