cocos2d-x出来很长时间了,受到的评价还是很不错的,有很多创业团队被它的跨平台特性吸引,开始用它来做IOS/Android上的游戏。虽然cocos2d-x已经足够优秀,程序员的工作却还有很多,而作为一个研发团队,有件事情必须在项目开始之前就考虑清楚:
换皮/山寨/原创
不久之前,一个换皮团队的主程跟我抱怨说老板不明白为什么他们的程序部可以只用一个月就让产品上线但增加一个系统两个月都搞不定。是的,换皮的效率优势的确明显,但策划是不甘寂寞的,所以无论是换皮还是山寨,策划会让你们的研发在某一阶段退化到原创。一旦回归原创,代码的结构将会变得非常重要,它直接影响程序员修改代码的效率。遗憾的是,在这种快节奏的研发环境下,程序员已经没有精力管这些了。你拿到手的换皮代码,它的原作者也是如此。
拯救程序员
与策划和美工一样,程序员也曾经热爱游戏,甚至更加热爱,但在入行多年以后的他们的心中,游戏究竟变成了什么呢?
你是否见证过这样的场面:
经理:策划,你的数值做完了吗?
策划:做完了,Excel发给程序员了。
经理:美术A,你的UI做完了吗?
美术A:做完了,所有图片打包发给程序员了。
经理:美术B,你的动画做完了吗?
美术B:做完了,所有序列帧打包发给程序员了。
。。。。。。
如果你没见识过,说明你还算幸运,不过据我所知,很多小团队就是这样的,流程中所有责任不明确的部分都被推给了程序员,因为只有程序员知道该怎么往下进行。
这不是策划或美工的错,事实上他们有劲使不上也很着急,一些cocos2d的工具能稍微缓解一下这类问题,但还远远不够。我们需要的是一套完整的,为当前项目量身定做的编辑器,不过对于程序员来说,额外开发这样的编辑器还不如之前的那些工作省事儿呢。
通用的编辑器框架
我不要求编辑器要像RPGMaker或者魔兽3那样把脚本指令都逐个可视化了,但至少策划的数值可以敲进去,美术的动画可以导进去,UI的布局可以在里边摆好,地图上的单位可以摆好,所有资源的名称可以起好。。。。。。
为了以最快速度得到一个为游戏量身定做的编辑器,我做了一个通用的cocos2d-x编辑器框架,用的是cocos2d-x 2.0.1和wxWidget 2.9.3。我为CCObject类增加了一个Serialize接口,根据调用者的不同,这个函数可以做三件完全不同的事:
1.读XML
2.写XML
3.生成PropertyGrid编辑器。
所以每当你开始一个新的游戏,只要把你派生类的Serialize函数写好,你的编辑器差不多就已经完成了。
Serialize函数大体上应该是这个样子:
void CCSprite::Serialize(Serializer* s, void *data)
{
CCNode::Serialize(s,data);
s->Image(data, "Texture", m_pobTexture);
s->Rect(data, "Rect", m_obRect);
s->Point(data, "Offset", m_obUnflippedOffsetPositio
nFromCenter);
s->Size(data, "Size", m_tContentSize);
s->Bool(data, "Rotated", m_bRectRotated);
}
元件
元件是实例的模板,它本身也是实例,只不过它还包含所有的子节点(如果元件是CCNode的派生类),编辑器是以元件为单位进行编辑的。
这个元件是商店物品列表中的一项,它本身是一个CCMenuItemLabel,它包含5个子节点,有4个需要在脚本中调用,要设置好它们的实例名,然后为这个元件添加一个函数
这个函数传入了一个物品实例item,根据它的属性来初始化界面,其实代码可以更简洁的,为了好懂就这么写了。元件的脚本要在编辑器里写,全局脚本需要新建一个与文档同名的Lua文件。
这是全局脚本中的一段代码,列出商店中的所有物品,我改写了CCMenu的alignItemsHorizontally函数,让它能按照行优先的方式格状排列,三个参数分别是列间距,行间距,最大列数。列优先的函数与它是对称的。同时我让CCMenu本身支持了滚动和裁减,不必再用CCScrollView,
最终效果是这样的:
其他的界面也用类似的方法来做,很简单
脚本:最天然的指令队列和场景栈
Lua很有名,以至于很多普通玩家都知道它,但作为程序员的你真的会用Lua吗?
“用Lua开发游戏有很多好处,比如它可以节省编译时间。”我不止一次看到这样的言论,看得我欲哭无泪。
我认为既然你选择Lua作为脚本语言,应该充分利用它的特性,它可以极大地简化你的代码,或者让你的代码结构变得完全不同。举个例子,比如你想让一个菜单 fadeOut之后从父节点删除,用C++的话需要把一个CCScaleTo和一个CCCallFunc组成CCSequence,然后在回调中删除菜单,这个代码就很糟糕,尤其是当Sequence很长,或者是你想让更了解该写什么的人来写这部分代码的时候(比如让剧情策划写人物对白),这种方式就显得太不人性化了。
脚本语言最大的优势就是可调度,你可以随时中断/恢复脚本的运行,这与线程无关。上边的例子,用Lua可以写成:
WaitForAction( menu:runAction(CCScaleTo:create(0.5,0)) );
在WaitForAction内部,脚本被挂起,直到传入的Action结束才会跳出。这样写的好处就是一系列的指令可以紧挨着写在一起,保证了代码的逻辑性和可读性。
你也可以把等待Action结束换成等待用户点击按钮,比如一个城镇的代码可以写成:
while 1 do
切换场景(城镇);
local s
= 等待用户点击按钮();
if s == "下一关" then
进入游戏(level+1);
elseif s == "酒馆" then
进入酒馆();
elseif s == "商店" then
进入商店();
else
break;
end
end
这段代码看上去跟游戏的流程设计图没什么两样,甚至可以交给策划来写。注意最外层的while循环,它的作用是让用户从酒馆或商店出来的时候能回到城镇这个场景继续做出选择。
小结
换皮/山寨/原创
不久之前,一个换皮团队的主程跟我抱怨说老板不明白为什么他们的程序部可以只用一个月就让产品上线但增加一个系统两个月都搞不定。是的,换皮的效率优势的确明显,但策划是不甘寂寞的,所以无论是换皮还是山寨,策划会让你们的研发在某一阶段退化到原创。一旦回归原创,代码的结构将会变得非常重要,它直接影响程序员修改代码的效率。遗憾的是,在这种快节奏的研发环境下,程序员已经没有精力管这些了。你拿到手的换皮代码,它的原作者也是如此。
拯救程序员
与策划和美工一样,程序员也曾经热爱游戏,甚至更加热爱,但在入行多年以后的他们的心中,游戏究竟变成了什么呢?
你是否见证过这样的场面:
经理:策划,你的数值做完了吗?
策划:做完了,Excel发给程序员了。
经理:美术A,你的UI做完了吗?
美术A:做完了,所有图片打包发给程序员了。
经理:美术B,你的动画做完了吗?
美术B:做完了,所有序列帧打包发给程序员了。
。。。。。。
如果你没见识过,说明你还算幸运,不过据我所知,很多小团队就是这样的,流程中所有责任不明确的部分都被推给了程序员,因为只有程序员知道该怎么往下进行。
这不是策划或美工的错,事实上他们有劲使不上也很着急,一些cocos2d的工具能稍微缓解一下这类问题,但还远远不够。我们需要的是一套完整的,为当前项目量身定做的编辑器,不过对于程序员来说,额外开发这样的编辑器还不如之前的那些工作省事儿呢。
通用的编辑器框架
我不要求编辑器要像RPGMaker或者魔兽3那样把脚本指令都逐个可视化了,但至少策划的数值可以敲进去,美术的动画可以导进去,UI的布局可以在里边摆好,地图上的单位可以摆好,所有资源的名称可以起好。。。。。。
为了以最快速度得到一个为游戏量身定做的编辑器,我做了一个通用的cocos2d-x编辑器框架,用的是cocos2d-x 2.0.1和wxWidget 2.9.3。我为CCObject类增加了一个Serialize接口,根据调用者的不同,这个函数可以做三件完全不同的事:
1.读XML
2.写XML
3.生成PropertyGrid编辑器。
所以每当你开始一个新的游戏,只要把你派生类的Serialize函数写好,你的编辑器差不多就已经完成了。
Serialize函数大体上应该是这个样子:
void CCSprite::Serialize(Serializer* s, void *data)
{
}
元件
元件是实例的模板,它本身也是实例,只不过它还包含所有的子节点(如果元件是CCNode的派生类),编辑器是以元件为单位进行编辑的。
这个元件是商店物品列表中的一项,它本身是一个CCMenuItemLabel,它包含5个子节点,有4个需要在脚本中调用,要设置好它们的实例名,然后为这个元件添加一个函数
这个函数传入了一个物品实例item,根据它的属性来初始化界面,其实代码可以更简洁的,为了好懂就这么写了。元件的脚本要在编辑器里写,全局脚本需要新建一个与文档同名的Lua文件。
这是全局脚本中的一段代码,列出商店中的所有物品,我改写了CCMenu的alignItemsHorizontally函数,让它能按照行优先的方式格状排列,三个参数分别是列间距,行间距,最大列数。列优先的函数与它是对称的。同时我让CCMenu本身支持了滚动和裁减,不必再用CCScrollView,
最终效果是这样的:
其他的界面也用类似的方法来做,很简单
脚本:最天然的指令队列和场景栈
Lua很有名,以至于很多普通玩家都知道它,但作为程序员的你真的会用Lua吗?
“用Lua开发游戏有很多好处,比如它可以节省编译时间。”我不止一次看到这样的言论,看得我欲哭无泪。
我认为既然你选择Lua作为脚本语言,应该充分利用它的特性,它可以极大地简化你的代码,或者让你的代码结构变得完全不同。举个例子,比如你想让一个菜单 fadeOut之后从父节点删除,用C++的话需要把一个CCScaleTo和一个CCCallFunc组成CCSequence,然后在回调中删除菜单,这个代码就很糟糕,尤其是当Sequence很长,或者是你想让更了解该写什么的人来写这部分代码的时候(比如让剧情策划写人物对白),这种方式就显得太不人性化了。
脚本语言最大的优势就是可调度,你可以随时中断/恢复脚本的运行,这与线程无关。上边的例子,用Lua可以写成:
WaitForAction( menu:runAction(CCScaleTo:create(0.5,0)) );
在WaitForAction内部,脚本被挂起,直到传入的Action结束才会跳出。这样写的好处就是一系列的指令可以紧挨着写在一起,保证了代码的逻辑性和可读性。
你也可以把等待Action结束换成等待用户点击按钮,比如一个城镇的代码可以写成:
while 1 do
end
这段代码看上去跟游戏的流程设计图没什么两样,甚至可以交给策划来写。注意最外层的while循环,它的作用是让用户从酒馆或商店出来的时候能回到城镇这个场景继续做出选择。
小结