码迷,mamicode.com
首页 > 其他好文 > 详细

《天天酷跑》游戏后台结构体标准化探 转

时间:2016-01-11 21:48:29      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

http://www.yxrb.net/thread-11839-1-1.html

在程序设计领域,程序就是数据结构加算法的理论早已深入人心。在手机游戏的后台系统中,数据结构就是各式各样的struct或class,遍布于数据存储(DB)、内存(业务逻辑)、网络(C/S交互协议),算法就是各种基于数据的业务处理逻辑了。


手机游戏后台数据结构有一些特点:


以整形数据为主,字符串类型比例很少,绝大部分数据可以用整形(直接或间接)表示。


相对大型端游,数据结构相对简单,绝大多数可以通过2-3层结构来抽象。


基于以上特点,《天天酷跑》后台设计了一套基于属性系统的结构体标准化表示方法,用于尽量统一C/S协议、逻辑处理和后台数据存储中用到的各式数据结构。


常规结构体定义


常规的结构体定义过程,就是程序员把用到的各种成员很直观地定义在代码(或者xml之类的模板中)中。如下图所示:

技术分享

 

图1.常规结构定义




图1的结构体定义简单、直接,但也有一些不太好的地方:


1、结构体看上去很类似,字段类型少量变化和变量名称的不同而已。定义时也是到处拷贝后稍作修改,就变成其他结构体的定义。


2、同一对象在程序中对应多个版本的结构定义,例如游戏中的“角色”可能在DB、逻辑、C/S协议中有多个版本的定义,在使用的过程中需要各种对接和转换。


3、结构体随着需求变化时,特别是在C/S协议中共用的结构体,需要不断升级协议的版本号,增加维护和兼容的成本。


如果把这些类似的结构体定义统一起来,施以标准化实施,并辅以统一的接口(算法),是否可以既避免上述的弊端,并能够获取到额外的收益呢?


本人在《天天酷跑》的后台开发过程中,进行了一些探索,并使用属性系统作为结构体标准化的载体来实现。


属性系统介绍


由于手机游戏后台中无法用整形(以及无法用整形类型间接)表示的数据占比非常之低,经过对比,选择uint32作为基础的数据类型。

技术分享

 

图2. 属性系统定义




属性系统架构上分为3个层次:


1、属性:Key/Value结构表示,Key是属性ID,Value是对象的值。用于表示对象的一个属性。


2、属性堆:多个属性组成一个堆,有一个堆ID。用于表示不同对象实例。


3、属性仓库:多个属性堆组合成一个属性仓库,用于表示对象的数组。

技术分享

 

图3.属性系统层次结构




属性系统特点


属性系统对结构体(对象)的定义进行了标准化,有如下一些特点:


1、不支持字符型成员,需要单独定义并与属性系统进行关联使用。


2、uint32类型表示所有的成员类型,其他类型需要转换。例如浮点转定点,64位整形用2个32位表示等。


3、本质上是key/value的二维数组结构。


4、可以通过ID(属性堆ID和属性ID)来随机读写成员,提供脚本化访问成员的能力。


5、标准化后可以使用统一的接口操纵(读写、序列化/反序列化等)。


在项目用使用属性仓库来表示各种游戏对象,例如角色的数值(类型、等级等)用AttributeStruct表示;单个角色对象通过AttributePile表示,角色对象之间通过属性堆 ID区分;玩家身上的角色列表通过AttributeWarehouse表示。


属性仓库的读写有3种方式:


1、一维索引。索引到某个属性堆,通过属性ID遍历读写堆中的属性成员,或者,根据属性堆ID 遍历到某个属性堆,通过索引访问堆中的属性成员。


2、二维索引。通过堆索引和属性索引来读写属性成员。


3、遍历式。完全获取不到索引信息时,使用属性堆ID和属性ID遍历整个属性仓库来对属性成员,性能低但功能强大,可以通过配置2个ID的方式读写任何成员。


DB中的属性系统


属性系统在DB中的应用,主要是玩家信息表中用于表示各种游戏核心对象的属性仓库字段。如下图:

技术分享

 

图4. DB中的属性仓库




玩家的基本账户信息、角色、坐骑、宠物、精灵、背包等,在DB玩家信息表中的载体,都是属性仓库。它们之间的不同,只是二维数组的2个维度的大小不同而已。例如角色仓库的属性堆数量少,但单个角色的属性数量多。而宠物的属性堆数量非常多,但单个宠物的属性数量少。业务使用不同的维度大的属性仓库来表示不同对象,主要用于减少空间的浪费。


代码中的属性系统


属性系统结合手机游戏后台程序设计的特定,在代码层级上,通常分为三层封装:


1、API层:通过模板封装一些基本的属性系统操作接口和算法。


2、逻辑层:直接操作DB中的属性仓库结构,封装具体业务的各种逻辑。


3、业务层:封装逻辑层的接口,加上日志流水、属性变化通知、DB保存等完整功能,供其他业务系统直接调用,屏蔽细节实现。

技术分享

 

图5.属性系统的代码层级




三层架构的好处是结构更加清晰,接口功能独立并易于维护。另外中间的逻辑层由于只操作DB字段,可以跨进程代码共享,例如idipsvr拿到玩家的DB字段后,引用gamesvr的逻辑层代码构造管理器,进行操作而不需要知道具体的业务细节。


C/S协议中的属性系统


客户端实现一套属性系统的封装后,就可以与服务器统一使用属性系统来解析玩家的数据了。在C/S协议中,当客户端请求玩家数据时,服务器会下发整个经过TDR打包后的属性仓库的结构。客户端TDR解包后,即可交给属性系统封装进行解析,然后再交由各种业务逻辑自己使用。


有以下几个好处:


1、客户端和服务器共享同一套数据格式,便于理解和数据处理。


2、减少协议升级的次数。基本上需求的增加和修改,只需增加一个属性定义交由客户端逻辑解析即可,不需要在协议中增加字段来支持。


3、存储系统的数据与协议返回的玩家数据都使用属性系统表示时,处理比较简单,dump出来甚至直接返回给客户端即可解析。


下图是使用属性系统来定义协议的例子。结算协议包含了大量游戏内统计数据,用于单局结算、数据校验、奖励发放、反作弊等大量逻辑运算。

技术分享

 

图6.游戏结算协议




属性系统与名称服务


名称服务(Name Service)用于记录属性名称、属性ID和属性所属对象之间关系。使用之前需要进行属性信息注册,例如< X_ATTR,ATTR_GOLDNUM,“ATTR_GOLDNUM”>三元组就定义了玩家金币数这个属性,属性属于X_ATTR范围,属性ID为ATTR_GOLDNUM,属性名为“ATTR_GOLDNUM”。


注册属性信息到名称服务器后,就可以用配表的方式完成很多功能,当然前提是底层的命令行解析和相应的业务逻辑代码调用。

技术分享

 

图7.公式化的商店配置表   

 

 


总结


通过属性系统,有条件性地标准化了前后台协议、后台业务逻辑和DB中数据存储的结构体表示,并通过一套封装的接口来读写结构体的成员,为开发的中后期带来非常多的便利,早期因为接口封装不完善、面向对象的思维方式等带来了一些沟通的成本。


通常标准化和灵活性是矛盾的双方,标准化之后就要求按照既定的标准(或者限制)来实施,在灵活性要求很高的场景(例如结构层级复杂、变化频繁的业务需求),会带来不便。但从《天天酷跑》后台的探索情况来看,属性系统非常适合在手机游戏中标准化表示各种结构体和对象。

《天天酷跑》游戏后台结构体标准化探 转

标签:

原文地址:http://www.cnblogs.com/bambomtan/p/5122368.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!