燕良@游戏开发

A game developer's blog

目前我公司开发的Nexus Engine的底层对象序列化使用了TinyXML来读写XML文件。TinyXML有两个不爽的地方,一是它的接口使用FILE*,另外一个是它对 wchar_t不能很好的支持。前阵子看Boost库的更新中多了一个PropertyTree,他在处理XML时用到了另外一个小的库 –RapidXML。既然间接的是Boost库的一部分,所以是值得一试的。于是找到其官方网站(http://rapidxml.sourceforge.net/)研究了一番。一看之下,甚是满意,也推荐给大家看看!

首先就是速度,据它自己宣称比TinyXML快30到60倍,比Xerces DOM快50到100倍!详细的测试比较请见其用户手册(http://rapidxml.sourceforge.net/manual.html)的“4. Performance ”一节。

其次它的设计非常的简洁,只依赖于标准库中的几个基本的类。它的输入输出都是字符串,这样很好,一个库就应该关注自己核心的内容,做尽量少的事情。它的API其实和TinyXML倒是有几分相似,用过TinyXML的人应该很容易上手:

TinyXML主要接口类     RapidXML的主要接口类

TinyXML主要接口类 RapidXML的主要接口类
class TiXmlDocument template<class Ch = char>
class xml_document
class TiXmlNode template<class Ch = char>
class xml_node
class TiXmlAttribute template<class Ch = char>
class xml_attribute

下面还是看一个具体的例子来体验一下,下面是TinyXML官方教程中创建XML文档的一段代码:

void build_simple_doc( )
{
// Make xml: <?xml ..><Hello>World</Hello>
TiXmlDocument doc;
TiXmlDeclaration * decl = new TiXmlDeclaration( “1.0″, “”, “” );
TiXmlElement * element = new TiXmlElement( “Hello” );
TiXmlText * text = new TiXmlText( “World” );
element->LinkEndChild( text );
doc.LinkEndChild( decl );
doc.LinkEndChild( element );
doc.SaveFile( “madeByHand.xml” );
}

下面是使用RapidXML实现类似功能的代码:

void build_simple_doc_by_rapidxml()
{
xml_document<> doc;
xml_node<>* decl = doc.allocate_node(node_declaration);
xml_attribute<>* decl_ver =
doc.allocate_attribute(“version”, “1.0″);
decl->append_attribute(decl_ver);
doc.append_node(decl);

xml_node<>* node =
doc.allocate_node(node_element,    “Hello”, “World”);
doc.append_node(node);

string text;
rapidxml::print(std::back_inserter(text), doc, 0);

// write text to file by yourself
}

下面是使用RapidXML分析XML的样例代码:

void parse_doc_by_rapidxml(char* xml_doc)
{
xml_document<> doc;        // character type defaults to char
doc.parse<0>(xml_doc);  // 0 means default parse flags

xml_node<> *node = doc.first_node(“Hello”);
string node_val = node->value();
}

好东西,大家分享!:D

前言

为了搭建新的技术平台,我在2009年,大概花去了半年的业余时间去试验混合语言编程的具体方案。早在几年前我就曾经感慨过,作为游戏开发者只掌握C++语言已经不够了,必须再掌握一种开发效率高的动态语言。很多人说C++过时了或者C++渐渐淡出主流了,我想至少在游戏开发领域不是这样,C++依然是不可或缺的,但是“只掌握C++已经不够了”!可以说底层使用C++,上层使用一种高级语言是我在开发《功夫世界》项目是就确定的长期目标;后来在开发《神兵传奇》的时候,其实也算是这样一种架构,我们使用的Unreal Engine 3它上层就是使用Unreal Script的,但是Unreal Script的设计还是显得有些陈旧了。上层选择一种什么样的语言,或者什么样的开发平台和C++搭配呢,这是一个问题。

09年上半年我主要实做了两种方案:C++使用Boost.Python包装,上层使用Python语言;C++使用C++/CLI包装,上层使用C#。其实Lua也曾经是一个选择,但是,无奈于我对面向对象已经“中毒太深”,Lua不能直接支持OO,而是需要用什么table去模拟,使我相当不爽。具体如何去比较两个方案的好坏,我个人认为去看别人的评论文章或者是评测结果,都是远远不够的,最靠谱的莫过于自己亲身一试。所以,我使用两个方案,在我的Nexus Engine的上层开发了同样功能的两套编辑器,都开发到了具有一定基础功能的程度。从中细细体会各个方面的问题,包括语言基础特性,标准库,IDE,运行效率等。接下来我讲主要说一下自己这个过程中具体的体会,以及最后的结论。

在进入具体细节之前,先说一下我对混合语言编程的一个整体的体会。混合语言编程,其实是大大的增加了整个系统的复杂度,所以,我们并不能追求对于项目中所有人在所有时间都更省力更省心,我们所能达到的目标是对于多数项目成员的大多数时间开发更简便,工作效率更高!既然是混合语言,往往中间需要一个“粘合层”,粘合层需要能够实现两种语言代码的互相调用,并且能够对于跨语言边界的数据问题提供尽量便利的机制。跨语言边界的问题可能包括对象生存期的管理,函数参数转换等等。

Python方案

Python是属于那种你一眼就会喜欢上的语言,真的很可爱,我非常喜欢他提供的这种统一的对象概念。我也曾深入C Python的源代码,对于它所实现的使用C语言描述的对象机制也深感敬佩,所以我决定首先尝试这种方案。

在粘合层方面几乎没有什么选择,要么是使用原生的C Python API,尝试了一下,细节太多,很容易出错;也找了一些其他开源的包装库,但是真的比Boost.Python都差太多了。Boost.Python的包装代码写出来很漂亮,很简洁。对于对象的生存期,也不用手动处理引用计数,相当方便了。值得一提的是它使用return_value_policy 很巧妙的解决了函数返回值的生存期管理问题。使用Boost.Python可以方便的包装C++已有的class到Python中使用,同样在Python中很方便的去派生这些类。当C++代码去调用Python派生类重载的虚函数的时候,就很完美的实现混合语言的多态。Boost.Python有一个非常大的缺点,就是相当的复杂,需要了解的大量细节,才能放心使用;另外它的具体实现,也只能想象其大体的思路,如果要我读懂它的整个代码,目前我对模板的掌握还达不到这个水平。所以用起来还是有些忐忑。

对于IDE方面,我尝试了很多,例如Wing等,可能是我比较偏好大型的IDE,所以最后我选择了Eclipse+PyDev。用起来还是满顺手的,书写,调试都比较方便,但是相对Visual Studio还是“手感”上差了一点。

因为我们的目标是开发一个游戏的编辑器,所以还需要界面库,我选择了wxPython。

最终花费三个月的时间,从摸索学习,到实现基础功能。

MS .Net方案(C++/CLI,C#)

记得几年前就对这个方案非常感兴趣,不过当时的Managed C++确实让我很倒胃口,那一次尝试就算是失败了。不过听说CLI这一套就是Lippman搞的,有鼓起勇气,这次一试才知道,现在的.Net已经不是当年的.Net了,而且Lippman的野心真的非常大,CLI也真的很强大!

我曾经想,如果使用Python方案,那开发人员只需要掌握C++、Python两种语言就可以了,如果使用.Net的话,似乎更复杂,因为要多一种语言。最后,我发现掌握C++/CLI这样一种新的编程原因,其难度应该说比掌握Boost.Python这样一个库是要低的!

IDE方面就不用选了,Visual Studio。C#代码的书写非常方便,Windows Form的可视化编辑也很方便。调试就更别说了,在单一的一个IDE里能够跨语言跟踪调试!特别是PropertyGrid控件,节省了很多工作量,而且还显得挺专业。

我不能不说我已经爱上了.Net!真的,以前看老外说用C++写引擎,C#写编辑器,还担心这样做会不会很累,现在看,完全是值得的。

还得说一下效率的问题。Python是出了名的慢的,据说比C++慢50倍;而C#代码借助.Net的JIT编译机制,效率损失还是很小的。

最后,使用.Net平台,还有一个最大的问题没有解决,就是代码的安全性的问题。如果客户端发布的EXE可以被很轻松的反编译,那外挂,私服可以说都很简单了,哪位高手有什么好方法,请指点。

比较与结论

最终选择了MS .Net平台方案。其实我是一个Linux爱好者和忠实用户,现在公司的服务器和我家里一台笔记本都装的Ubuntu。这么多年来,一直想要摆脱微软,哈哈。也许是宿命吧,MS还是很强大的。对于.Net平台的强大,我想很多人比我在行多了,所以我也就不深说了,其实我还是一个这方面的新手啊。给我最大的感触有两点:

  1. 跨语言的调试:我可以从C#代码一直Step Into到C++/CLI代码,一直到Native C++代码;我想MS吹的跨语言特性还真不是虚的;
  2. Windows Forms还真是很方便,以至于我很乐于为Menu,ToolStrip等配上小图标,一下子整个界面就显得专业多了,呵呵;
    MS .Net/C#对于我、我们这个团队还是一个新东西,肯定还需要很多实践、摸索才行。所以,欢迎有.Net平台开发经验、又对游戏开发感兴趣的朋友加入我们!

    以前啊,每当我收到网易,搜狐等公司的人的应聘简历,其实都有一丝的不解:大公司实力雄厚,资金有保证,人才有优势,应该是很有吸引力的才对。很多人都是费了一番力气才挤进去的,为什么又这么多人要出来呢。我现在在所谓的大公司干了一圈,自己也出来了,当然这个原因是很复杂的。今天我想清楚了原因之一。

    今天和以前的一个同事聊天,得知原来的项目程序员团队已经达到了20多人的规模。从公司的角度来看,人家“不差钱”啊,所以呢,就算只有10个人的活,人家也可以招20个程序员来干,这叫做“人才储备”,说白了也就是你们走几个人对我没什么影响。咱且不说这种策略对于公司来讲是否正确,但是对于我们每个有上进心的程序员来讲,我们是亏的!对于我们每个人来讲,最宝贵的就是时间了。如果我们在一年的时间中,只完成了半年的工作量,这对于我们来讲,损失的是时间。回顾我自己从业这10年,每个成长快的阶段都是顶着120%工作压力的时候,有很多痛苦加班的经历,也是最能够出成绩的,甚至说成了现在炫耀的资本。所以一个精明的,有上进心的程序员恐怕很难忍受这种浪费,也就不难理解为什么那么多人不乐意安逸的呆在大公司了。

今天又一个面试者被我拒绝了。每次拒绝像他这样充满热情的同学,都令我心有戚戚焉。所以,往往在拒绝人家之后,我都会给一些学习的建议,并鼓励说半年之后可以再投简历!我会根据每个人的情况不同给一些不同的建议,但是这些年下来,大概也是有很多共通的地方,今天有时间总结一下。

总体来说,我领导的团队其实是乐意带新人的,但是新人要有一定的编程基础,要有一定的潜力,还要有一定的“人品”。所以我对想进入游戏业的同学们的建议是要把C++语言的基础打好。这里面首先要认识到,在学校学的那些只是C++的常用的语法,这是非常不够的!可以说学校里面学的C++和咱们工作中用到的C++几乎是两码事。所以有几本书是必须要看的,并且把书中的练习题都做一遍,首先就是Lippman的《C++ Primer》,如果实在时间紧张,至少《Essential C++》是要看一遍的。我一直说其实咱们编程是一个动手活,所以光看书还不行,至少应该写一个一万行以上的程序。当你完成了一个一万行以上的C++程序之后,你会发现自己很多想法都变了。我有时会建议写一个俄罗斯方块之类的小游戏,或者是一个聊天室的服务器+客户端等等。

还有不少面试者向我咨询游戏培训相关的事情,例如XXX培训是否值得去学?其实,就我面试经验来将,对大多数培训机构出来的人并没有什么加分,因为他们带的作品往往是“和老师或其他同学一起做的”,里面具体的思路自己都讲不清楚。所以,不能说游戏培训一点用没有,只能说还得看个人的基础,我相信基础好的遇到一个好老师,还是能学到不少东西的。但是如果还是很表面化的去过一遍里面的课程,恐怕真的是没什么意义。

以上,希望对想进入游戏行业的朋友有帮助。

Powered by WordPress Web Design by SRS Solutions © 2010 燕良@游戏开发 Design by SRS Solutions