1.首先,数据驱动是什么?
这个问题,我不敢回答,因为我也是刚刚从《游戏编程精粹1》这本书上了解到的,我并不完全了解它。关于数据驱动的介绍,可以参考《游戏编程精粹1》的第一章第一节(我不是来卖广告的...),或者参考以下地址:
http://www.cnblogs.com/tadi314/archive/2010/03/11/1683795.html
不过,从它的介绍中可以看出,它至少可以减少使用硬编码,一定程度上分离逻辑与数据。
2.然后,Stop GMO是啥玩意?
如果不嫌弃,可以参考一下我的上一篇博文,里面有Stop GMO的介绍和代码地址等。简单来说,Stop GMO就是本菜鸟学习cocos2d-x时尝试编写的一个横版游戏(应该说,是山寨原版Stop GMO的一份劣质品)。
3.那么,数据驱动与Stop GMO有什么关系?
说实话,它们之间本来没有半毛钱关系。我现在时想将数据驱动的设计思想应用到Stop GMO,让它们有一点关系,好让我山寨的Stop GMO沾沾光...
-----------------------------------------------我是分割线-----------------------------------------------
如果有哪位好心人可以忍住恶心读一读我那份写得很烂的Stop GMO的代码,就可以发现,游戏场景中的Enemy类是所有怪物类的父类,它将派生出Carrot,Corn等怪物类型。而其实Carrot类与它的兄弟类Corn可以说是完全一样的,它们的行为,数据类型上完全一致,只是数据的具体值不一样而已(例如攻击力、生命值或者动画贴图不一样)。这样,我们可以尝试应用数据驱动的思想,将这些数据的具体值编写到一个外部的文件里(如xml文件),那么Enemy不再派生出Carrot,Corn等类,而是Enemy自己就作为一个可实例化的类,但是在实例化之前接受来自外部文件所定义的具体数据值,影响自身的初始化,从而模拟“派生”Carrot,Corn等类。
应用数据驱动,读取外部文件,从而模拟出派生的行为,究竟有什么好处呢?看回原来的设计,Enemy是不能实例化的,而是派生出Carrot等子类,Carrot在构造函数中定义了自身的属性数值,如生命值、攻击动画等。但实际上,Carrot并没有对Enemy进行任何的扩展,它只是具体定义了一些数据而已。这似乎有点“类冗余”(这个词是我瞎编的...)。我们每次想要添加一种新的怪物的时候,都要修改原来的代码,派生出一个新类型。但是,如果我们将怪物的具体数值放到外部文件,将Enemy设计为可实例化的,Enemy接受外部分文件数据进行初始化,则经过一定的设计后,可以做到添加新怪物类型的时候,不需要修改原代码,只是修改一下外部的数据文件而已。
-----------------------------------------------我是分割线-----------------------------------------------
(好吧,或许一部分人还不清楚我上面一段话想要表达什么。没关系,是我的表达能力有问题,不关你事的~~~)那么,选择什么文件类型来存储这些具体数据好呢?我选用的是xml文件。那么,我们现在考虑解析xml文件的问题。对于我这样的懒人和菜鸟,第一个想到的不是自己写一个解析程序,而是上网看有没有相应的函数库。经过谷歌+百度后,我发现cocos2d-x里面有个CCSAXParser支持XML的解析;同时,也有个开源的C++ XML解析器tinyxml。不知道为什么,我更倾向于用tinyxml。可能是我想到我正在做的毕业设计也需要xml文件保存数据,tinyxml作为一个独立的库比较方便吧。
当我想下载tinyxml库的时候,我又发现了tinyxml2,所以我就下载了tinyxml2,所以,我就尝试用一下tinyxml2了。下面给出一个简单的例子代码,是我尝试设计的用作Stop GMO中保存的Enemy具体数据的格式,以及一个简单解析尝试:
http://www.oschina.net/code/snippet_115087_17336
我们将数据保存到外部文件,再解析到程序中应用,则可以在添加新的单位(怪物)类型不需要修改程序代码,使得程序变得更有扩展性。这种方法,在RTS游戏中应该比较常用吧(魔兽争霸的世界编辑器里头的数据编辑器?)?
来源:oschina
链接:https://my.oschina.net/u/115087/blog/101893