游戏元数据模块设计
模块设计目的
在我们的游戏中会创建许许多多的实例对象,比如‘特效’,‘怪物’,‘人物’,‘模块’,‘UI’等,对于这些对象创建都会各式各样,五花八门,当然我们可以写各种各样样的管理器去创建对象,如果又重新加入一种对象,那么就不是那么好用了,肯定在游戏中会不断添加对象,再有万一那天我们修改某类的属性呢,当然使用继承是最简单的方式,但是如果就因为修改一个值,这不就太坑爹了。所以,元数据模块的目的就是简化各种游戏对象的创建方式,并且提供游戏对象的预加载功能等。
数据和程序分离
上面我已经提到,为了一个参数去重写一个类太坑爹了。
1. 那么可以把这个参数做到全局配置中吗?
这是可以的,但是这样创建的所有对象参数都会改变,这估计不符合我们预期;
2. 那么可以再创建对象时把参数传递进去修改吗?
这也是可行的,但是需要在每次创建对象的时候传递参数会不会太麻烦,以后修改的参数多了,你感觉爽否。
所以现在我们要使用数据和程序分离
,数据就是游戏对象的配置,程序就是游戏对象的程序。这样我们只需要一个JSON文件就可以配置一个或者一种游戏对象。而且这个对象是可以在使用的时候加载JSON配置,并创建游戏对象的。
游戏对象创建分类
我们需要创建的游戏对象一般可以分为三大类:
纯程序
创建的对象,这类一般只有程序,比如游戏的脚本对象。程序 + 类配置
创建的对象,可以创建任意个对象,比如特效。程序 + 配置
创建的对象,这算游戏中的单例对象,比如UI等。
如何对象加进元数据呢?
那就要使用到我们前面提到的索引模块
,我们会在元数据模块中收集每个对象的meta(纯程序)、class(类)和object(对象)的索引路径, 创建时会根据索引路径查找对象配置。
元数据模块重要函数
registerModule(modname, metaipath, classipath, objectipath)
注册模块,需要使用到模块名、元数据索引路径、类索引路径和对象索引路径unRegisterModule(modname)
注销模块getMeta(modname, metatype)
获得指定模块的元数据,可能很少使用getClass(modname, clsname)
获得指定模块的类数据,如果存在getObject(modname, objname)
获得指定模块的对象,这是单例对象经常使用的createObject(modname, metaorcls, ...)
创建指定模块的对象,metaorcls
表示元数据对象或者类对象,这个函数会优先尝试使用类对象创建,如果不存在则使用元数据对象创建
当然,元数据模块存在对象的预加载功能这里就不介绍了。
元数据模块的用法
比如,创建UI管理模块:
metaMgr:registerModule("__UI__", "src/uis/", nil, "res/uis/frames/")
其中__UI__
为模块名,"src/uis/"
为程序索引路径,"res/uis/frames/"
为对象索引路径。一般UI都是单例的,所以这里没有类索引路径。metaMgr:getObject("__UI__","message")
由于UI是单例,所以我们直接通过模块getObject
获得UI对象。
再比如,我们要做游戏的字体管理模块:
metaMgr:registerModule("__Font__", "src/fonts/", "res/fonts/")
其中__Font__
为模块名,"src/fonts/"
为程序索引路径,"res/fonts/"
为类索引路径。字体模块,一般会根据类创建多个对象。metaMgr:createObject("__Font__", "bmfont16", "test", nil)
根据指定字体bmfont16
创建标签test
并且参数为nil
(不使用额外参数)。一般我们把bmfont16
定义在"res/fonts/"
类索引里面,这样就是根据的这个类创建的标签。
好了,所有的对象创建都类似于上面的做法,用起来是不是很简单。
元数据模块很重要
元数据模块管理并且简化了游戏对象使用,是当前游戏框架中很重要的模块,很多其他模块都会引用它,地位仅次于索引模块。