2013年12月14日 星期六

cocos2d-x与CocosBuilder笔记:HelloCocosBuilder

http://blog.csdn.net/wayne5ning/article/details/8652371


本文将一步一步展示怎样将CocosBuilder导出的东西加入到cocos2d-x工程中,生成可执行程序。这涉及到几个问题:
  1. 安装CocosBuilder,然后大致了解其功能
  2. 使用CocosBuilder编辑并保存
  3. 将CocosBuilder的输出加入到cocos2d-x工程中
下面逐一介绍。cocos2d-x有一个比较全面的例程,但是比较难于理解。本文只是抽取其中一部分,主要实现如下的功能:启动时,界面上有一个字标(Label)和一个按钮。这个字标具有一定的动画效果;当点击这个按钮时,要有响应。界面大致如下

1 CocosBuilder功能初探

 CocosBuilder只能在Mac下边安装,直接从官网下载app文件即可。如果只有Windows系统,则需要在虚拟机中安装MAC系统,具体参考“[资料整理]虚拟机安装Lion及XCode4”。
安装好后,打开可以看到如下的界面(此图包含了一些注释,版本为2.1):
从图中可以看了,此界面从逻辑上大致分为7个版块。5和6是可以伸缩的,通过拖动调整大小,5或6其中可以有一个不被显示。

1 菜单

包括CocosBuilder, File, Edit, Object, View, Animation, Window, Help等菜单。
CocosBuilder涉及至此软件的一些操作,如关闭、更新等;File针对一个工程的操作,如打开、关闭、发布等;Edit提供一般的编辑操作,如复制、粘贴等;Object提供场景内容上操作,如对齐,选择等;View为视图操作,如放大、缩小等;Animation提供动画编辑与相关的操作,如插入关键帧等;Window提供窗口管理;Help提供搜索及说明文档入口。
常用:File/Publish, Animation/Insert Keyframe/*等, Object/*

2 调整视图

View菜单下的一些快捷操作

3 场景元素类型

由图中可以看出,能够放在cocos2d-x场景中的元素都可以在CocosBuilder中编辑。图中从左到右依次是
  • Node:CCNode;
  • Layer:CCLayer, CCLayerColor, CCLayerGradient, CCScrollView;
  • Sprites:CCSprite, CCScale9Sprite;
  • Label:CCLabelTTF, CCLableBMFont;// 还差CCLableAtlas
  • Menu:CCMenu, CCMenuItemImage;  // 缺少CCMenuItemFont
  • Control:CCBControlButton;                 // 与CCMenuItem区别是什么?
  • FX:CCParticleSystemQuad;                // 粒子编辑器惊讶,CCParticleSystemPoint已经不推荐了,所以有没有无所谓
  • CCB:CCBFile                                         // 似乎是可以嵌套?
  • 另外还有插件功能:TODO: 补充实用插件
加上菜单上的由此可见,功能相当强大了。

4 工程视图

当把ccbproj放到cocos2d工程下的Resources目录下时,用CocosBuilder打开此ccbproj,会显示此Resources目录下的所有资源文件,它们就显示在工程视图中。如下图所示
注意到plist和文件夹是可以展开的。关于plist请参考官方文档

5 效果预览

CocosBuilder是所见即所得的,编辑结果可以立即在此窗口中预览。如下

6 场景元素列表及动画编辑区

这儿主要是动画编辑,可以设定关键帧、设置关键帧之间的过渡方式(EaseAction)、总动画时间等,每个元素可以单独进行动画编辑。本文对"Hello CocosBuilder"字标做了一个动画,设定了两个关键帧,使用BounceIn/Out的过渡方式,界面大致如下:
此区域左半部分列出了窗口中元素的层次关系,它们组成一个树状结构,也就是Cocos2d中场景描述的图形化展示。最顶层是一个CCLayer,它可以有很多元素作为孩子,每个孩子可以对它的一些属性设置动作,如Visibility, Position, Scale, Rotation, Opacity, Color。总之,cocos2d中Action能用Action来实现的东西都可以在这儿编辑。结点的位置决定了它的zOrder相对深度,越往下,则它离观察者越近(可以通过在左侧拖动或者Object菜单来调整它们的相对深度)。

7 场景元素参数设置(用于生成代码)

对于不同的场景元素有不同的参数需要设置,对于CCLabelTTF,其参数设置界面如下:

2 使用CocosBuilder编辑并保存

CocosBuilder自带有说明文档,主要的编辑可以参考此文档。CocosBuilder对内容的管理也是使用“工程”,首先需要新新建一个CocosBuilder工程(后缀名为ccbproj)。需要注意的是,CocosBuilder的工程只有在cocos2d工程目录下的Resources目录中时,才可以进行编辑。这一点在说明文档中说得不是很能让人注意到。
使用CocosBuilder编辑场景,主要在涉及三个方面

1 添加元素

可以从两个地方添加元素,一是从窗口区域4中选择一个资源,拖到到窗口区域6中左侧;二是点击窗口区域3中相应元素,此元素自动加入到窗口区域6中的列表中。

2 设置元素属性

如前所述,窗口区域6中左侧描述了场景中元素的组成关系,这是可以通过拖动来改变的;它们的位置可以通过在窗口区域5中拖动来实现,并且通过Object来辅助对齐并设置z-order;通过窗口区域7可以设置它们的更多参数。本文要关心的是有两个地方,一个是顶层Layer的类名,另 个是按钮的响应函数,它们的设置会影响代码的实现。它们都涉及到怎样将CocosBuilder的描述产生出具体的实例与行为(函数)。为产生具体实例,在Cocos2d-X中实例的生产类与一个名字建立映射,这个名字再与CocosBuilder中的实体建立映射;为了得到函数,Cocos2d-X的函数指针与一名字(字符串)建立映射,这个名字与CocosBuilder中的按钮建立映射。

3 设置元素动作

在窗口区域6中,选中一个元素,然后通过Animation/Insert Keyframe来对其中一个可动作属性添加动作。可以添加多个关键帧。相邻两个关键帧之间自动建立插值机制,并且这个插值机制可以通过右击此插值区域,来选择其中一种插值机制。关于动画的编辑,请参考Skeletal animation

3 将CocosBuilder的输出加入到cocos2d-x工程中

在CocosBuilder中选中一个ccb文件,然后点击File/Publish便会生成一个ccbi文件(本文的为HelloCocosBuilder.ccbi,注意先保存[Save]然后再发布[Publish],否则生成的内容是不全的)。CocosBuilder的每一个场景内容(ccb文件)导出后为一个ccbi文件,将这些ccbi文件和资源文件一起放到cocos2d-x的Resources目录下边(目录结构不要改变),然后就可以开始在cocos2d-x工程中使用这些ccbi文件了。使用这些ccbi文件,cocos2d-x的例程中提供了一个比较复杂的实现,现在我整理一下对于单个ccbi文件需要做什么工作。
为了加载一个场景(由ccbi描述),在cocos2d-x中需要做如下事情:
定义一个场景类,并定义这个类的生产类,然后还要做一引起字符串到类、字符串到函数的映射(cocos2d-x提供了一些宏来辅助映射),具体如下(注:这里我将声明和实现放到一起以便更好理解,具体实现时请将声明和实现分离):

定义场景类将做好映射

  1. // 类名可以是任意  
  2. // 从这4个类(接口)继承是必要的,继承顺序可以不同  
  3. class HelloCocosBuilderLayer  // 可以是任意名字  
  4.     : public CCLayer  
  5.     , public CCBSelectorResolver  
  6.     , public CCBMemberVariableAssigner  
  7.     , public CCNodeLoaderListener  
  8. {  
  9. public:  
  10.     static CCScene* scene();  
  11.     ~HelloCocosBuilderLayer(){};  
  12.   
  13.     // 封装实例创建方法, 必须  
  14.     CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(  
  15.         HelloCocosBuilderLayer, create);  
  16.   
  17.     // 响应按钮点击事件,非必须,如果方法,则事件不会有响应  
  18.     void onButton1Clicked(CCObject * pSender,  
  19.         CCControlEvent pCCControlEvent)  
  20.     {  
  21.         // 这里面的实现不重要  
  22.         CCLabelTTF* pLabel = CCLabelTTF::create("Button Is Clicked""Arial", 34);  
  23.         pLabel->setColor(ccc3(255, 0, 0));  
  24.         addChild(pLabel);  
  25.         pLabel->setPosition(ccp(getContentSize().width/2,  
  26.             pLabel->getContentSize().height));  
  27.     }  
  28.   
  29. private// 访问权限不一定要是private  
  30.     // 将MenuItem名字与响应函数做映射  
  31.     virtual SEL_MenuHandler onResolveCCBCCMenuItemSelector(  
  32.         CCObject * pTarget, CCString * pSelectorName)  
  33.     {  
  34.         // 以后再讨论此问题  
  35.     }  
  36.     // 将CCControl名字与响应函数做映射  
  37.     virtual SEL_CCControlHandler onResolveCCBCCControlSelector(  
  38.         CCObject * pTarget, CCString * pSelectorName)  
  39.     {  
  40.         // 说明见注释“Control与响应函数映射”  
  41.         CCB_SELECTORRESOLVER_CCCONTROL_GLUE(  
  42.             this"onButtonClicked", HelloCocosBuilderLayer::onButton1Clicked);  
  43.         return NULL;  
  44.     }  
  45.     // 将变量名字与变量做映射  
  46.     virtual bool onAssignCCBMemberVariable(  
  47.         CCObject * pTarget, CCString * pMemberVariableName, CCNode * pNode)  
  48.     {  
  49.         // 以后讨论此问题  
  50.     }  
  51.     // 当此场景加载完成后,如果需要做一些操作,则在此方法中添加  
  52.     virtual void onNodeLoaded(  
  53.         CCNode * pNode, CCNodeLoader * pNodeLoader)  
  54.     {  
  55.     }  
  56.   
  57.     HelloCocosBuilderLayer(){};  
  58. };  

定义场景生产类

  1. // 类名任意  
  2. class MyLoader : public CCLayerLoader  
  3. {  
  4. public:  
  5.     CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(  
  6.         MyLoader, loader);  
  7.   
  8. private:  
  9.     CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(  
  10.         HelloCocosBuilderLayer);  
  11. };  

 使用场景类与场景生产类

在此场景的次结点(一般是Scene)中适当地方调用如下代码
  1. // 将ccbi中场景名与场景产生类建立映射  
  2. CCNodeLoaderLibrary * ccNodeLoaderLibrary  
  3.     = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();  
  4. ccNodeLoaderLibrary->registerCCNodeLoader(  
  5.     "MyLoader", MyLoader::loader());  
  6.   
  7. // 用CCBReader解析ccbi文件,生成场景对象node  
  8. CCBReader * ccbReader = new CCBReader(ccNodeLoaderLibrary);  
  9. CCNode * node = ccbReader->readNodeGraphFromFile("HelloCocosBuilder.ccbi"this);  
  10.   
  11. ccbReader->release();  
  12.   
  13. // 加入到父类中  
  14. if(node != NULL) {  
  15.     this->addChild(node);  
  16. }  
 完结。
注:cocos2d-x版本 -- cocos2d-2.0-x-2.0.3
此文还在完善过程中,欢迎各种意见与建议,谢谢。




1楼 Mikiller3 2013-06-21 15:42发表 [回复] [引用] [举报]


CCControlButton 和CCMenuItem区别很大啊~首先他们的背景图类型不一样,CCControlButton对应CCScale9Sprite, CCMenuItem对应CCSprite.之后的区别几乎都源自于这两种sprite,ControlButton可以缩放(不过有个bug,需要改源码,具体记不清了,网上一搜就有),具有点击后的动画效果(不是简单地图片切换,而是放大缩小之类的形变).另外,CCControlButton可以单独使用,CCMenuItem好像一定要配合CCMenu使用吧?
个人在用惯CCControlButton后,几乎就不再使用MenuItem了...CCSprite也几乎全用CCScale9Sprite替换了