现在的位置: 首页 > 综合 > 正文

根据CocosBuilder文件自动生成代码

2013年01月27日 ⁄ 综合 ⁄ 共 5113字 ⁄ 字号 评论关闭

本文主要讲述怎样根据Cocosbuilder生成的ccb文件自动生成相应的代码,主要以生成cocos2dx对应的C++文件为例子来说明。


转载请保留原文地址:http://blog.csdn.net/liangneo/article/details/8851870

cocosbuilder是一个非常好用的开源工具,可以用来编辑ui布局,粒子系统,简单的帧动画等。在编辑器中可以设置UI回调函数名,绑定编辑对象到Owner或者Doc root上以及为自定义的对象设置自定义的属性。以上三点都需要相应的代码来支持。因此在编辑完成游戏场景后,一定要写相应的代码。但是写相关的代码是比较繁琐的,很容易出现错误。

如果在场景编辑完成后,能根据场景文件自动生成代码框架将会节省不少工作量,并且减少出错的概率。下面分三个部分来一一说明如何实现自动生成代码,第一部分将会大体描述如何绑定代码,第二部分分析如何自动生成代码,第三部分给出代码实现

一 场景编辑器中控件与代码绑定

1.菜单回调函数,如下图设置,可以指定一个Selector和Target,在编辑器中设置后,将对应的target对象的某一个拥有特定签名的函数与selector指定的字符串绑定起来后,当菜单按下时,就会回调的相应的函数。

我们先来研究一下,在Cocos2dx中是如何将MenuItem的回调绑定到相应代码中的。

a.假设Document root对应的类为TestAutoGenLayer,为了实现绑定TestAutoGenLayer必须继承一个

cocos2d::extension::CCBSelectorResolver,然后实现 函数

    virtual cocos2d::SEL_MenuHandler onResolveCCBCCMenuItemSelector(cocos2d::CCObject * pTarget,
cocos2d::CCString * pSelectorName);

在该函数中完成代码绑定。

b.绑定代码如下:

SEL_MenuHandler TestAutoGenLayer::onResolveCCBCCMenuItemSelector(cocos2d::CCObject *pTarget, cocos2d::CCString *pSelectorName)
{
CCB_SELECTORRESOLVER_CCMENUITEM_GLUE(this,"BackPressed",TestAutoGenLayer::BackPressed);
return false;
}

上面代码将selector指定的值”BackPressed“与TestAutoGenLayer::的BackPressed函数绑定起来。(注:Selector的值可以函数名不相同)

c. BackPressed的代码框架如下

void TestAutoGenLayer::BackPressed(cocos2d::CCObject * pSender)
{
//在这里实现回调功能
}

2.ControlButton回调

假设一个ControlButton在cocosbuild中有如下设置, 

Document root还是TestAutoGenLayer类,在该类中实现CCBSelectorResolver的onResolveCCBCCControlSelector函数,假设代码如下

SEL_CCControlHandler TestAutoGenLayer::onResolveCCBCCControlSelector(cocos2d::CCObject *pTarget, cocos2d::CCString *pSelectorName)
{
	CCB_SELECTORRESOLVER_CCCONTROL_GLUE(this,"DoNotPress",TestAutoGenLayer::DoNotPress);
	return false;
}

DonotPressMe的代码框架如下

void TestAutoGenLayer::DoNotPress(CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent)
{
//在这里实现控件回调功能
}

3.将场景中的对象赋值给指定的对象,选择一个对象后,修改code connection属性,如下图

可以选择将一个对象赋值给 Document root或者是owner,指定一个绑定名字即可,下面绑定到Document root为例,假设root是TestAutoGenLayer类,被绑定的对象为CClabelTTF,为了实现绑定,a.TestAutoGenLayer必须承继于cocos2d::extension::CCBMemberVariableAssigner,并且实现方法onAssignCCBMemberVariable,b.TestAutoGenLayer
必须定一个类型为CCLabelTTF的成员变量

绑定代码段如下

bool TestAutoGenLayer::onAssignCCBMemberVariable(cocos2d::CCObject *pTarget, cocos2d::CCString *pMemberVariableName, cocos2d::CCNode *pNode)
{	CCB_MEMBERVARIABLEASSIGNER_GLUE(this,"m_String2",CCLabelTTF*,this->m_String2);
	return false;
}

4.为自定义类型设置custom properties,具体在编辑中如何设置custom propertyies就不在些描述了,下面只专主如何将自定义属性绑定到代码中,cocosbuilder支持的自定义类型有4种:int,float,string,bool。假设在cocosbuilder中设置了4个自定义类型的变量,分别是

int 类型的m_intVal;

float类型的m_floatVal;

string类型的m_stringVal;

bool类型的m_boolVar;

为了实现绑定到类TestAutoGenLayer,

a.该类必须实现类cocos2d::extension::CCBMemberVariableAssigner的接口onAssignCCBCustomProperty

b.定义与自定义类型相关的变量

绑定代码如下:

bool TestAutoGenLayer::onAssignCCBCustomProperty(cocos2d::CCObject *pTarget, const char *pMemberVariableName, cocos2d::extension::CCBValue *pCCBValue)
{
    if (pTarget == this)
    {
		if (0 == strcmp(pMemberVariableName, "m_intvar")){
			m_intvar = pCCBValue->getIntValue();
			return true;
		}
		if (0 == strcmp(pMemberVariableName, "m_floatVar")){
			m_floatVar = pCCBValue->getFloatValue();
			return true;
		}
		if (0 == strcmp(pMemberVariableName, "m_stringVar")){
			m_stringVar = pCCBValue->getStringValue();
			return true;
		}
		if (0 == strcmp(pMemberVariableName, "m_bool")){
			m_bool = pCCBValue->getBoolValue();
			return true;
		}

	}
	return false;
}

二. 如何实现自动生成代码

 

 

         根据上面的分析,我们知道一共有四种类型的绑定代码需要生成,每种类型的绑定都需要生成声明和实现(.h文件与.cpp文件),另外还要生成类的定义、构造函数及文件的尾部。下面来一一分析需要生成代码。

1.    MenuItem回调

a)       头文件:生成Selector对应的函数声明

b)       cpp文件,生成空的Selector函数体,

c)       cpp文件 生成绑定代码

2.    ControlButton回调

a)       头文件:生成Selector对应的函数声明

b)       cpp文件,生成空的Selector函数体,

c)       cpp文件 生成绑定代码

3.    场景对象赋值到宿主

a)       头文件,生成变量声明

b)       cpp文件,生成绑定代码

c)       构造函数,变量赋初值

4.    自定义变量赋值到宿主

a)       头文件,生成变量声明

b)       cpp文件,生成绑定代码

c)       构造函数,变量赋初值

5.    杂项

a)       类定义生成

b)       构造函数生成

c)       头文件尾部生成

要生成这些代码需要些什么信息呢,为了方便说明,直接上代码

struct TypeName {
    TypeName(const std::string& t="",const std::string& n="")
    :type(t),name(n){}
    std::string type;
    std::string name;
};

    std::stringm_className;                        //要生成的类名
    std::string m_baseClass;                        //生成类的父类
    std::vector<TypeName>m_listAssignMember;       //需要赋值的场景对象
    std::vector<TypeName>m_listCutomProperty;      //需要赋值的自定义变量
    std::vector<std::string>m_listCContorlCallBack;//menu回调函数名
    std::vector<std::string>m_listMenuCallBack;    //control回调函数名

 这些信息从什么地方可以获取呢,只用解析cocosbuilder生成的ccb文件就可以得到了。

有了上述的信息,我们再定义一些代码模板,替换和复制代码模板就可以生成相关代码了。 以类的定义生成来说明。类的代码模板如下

 

 

//  %class_name%.h
// 
//
//  this code is auto generate by the toolcreated by neo. Email andsonliang@gmail.com
//
//
 
#ifndef __autogen_ccbuilder__%class_name%__
#define__autogen_ccbuilder__%class_name%__
 
#include"cocos2d.h"
#include"cocos-ext.h"
 
class %class_name%
:publiccocos2d::%base_class%
, publiccocos2d::extension::CCBSelectorResolver
, publiccocos2d::extension::CCBMemberVariableAssigner
, publiccocos2d::extension::CCNodeLoaderListener
 
{
public:
    %class_name%()
:%base_class%()

 

在生成代码时,读入代码模板,将%class_name%替换为m_className,%base_class%替换为m_baseClass就可以了。

其余的现实方式差不多,就不在此一一说明,有兴趣的请直接参考原代码。

 下面描述一代码下生成流程

如上图示,首先解析器将ccb文件解析,生成关键字列表,然后生成器根据关键字列表,生成对应的代码段

 

三 实现代码

执行文件

四 总结

         有了自动代码生成后,重复copypaste代码的工作减少了不少,而且可以避免犯一些低级的错误。唯一美中不足的是,生成的Cpp代码要经过编译才能运行而不能热启动,这样不利于快速开发。从改动查看结果还要经过中间的编译过程,如果在开发时生成可以直接执行的脚本文件例如lua,在发布时生成需编译的cpp文件。这样即解决快速开发。又不损失最终产品的运行效率。这将会是两全其美结果,至于如何实现这样的效果,我将在以后文章中再作进一步的论述。

抱歉!评论已关闭.