从零开始学习CocosBuilder

本文由 杨世玲 (泰然教程组)原创,转载请注明出处并通知泰然!!
CocosBuilder是Cocos2d系列的配套开源工具,最新的版本是3.0a, 也是我们这个文章所采用的版本.CocosBuilder目前只有OS X版本, 没有Windows的版本, 而且开发语言是Objective-c, 估计移植难度会比较大. 我想这个也是其不够流行的原因吧.

如果你是CocosBuilder的熟客,那么你一定会记得CocosBuilder v2.x以前版本附带的例子(以下我们提到例子即为这个例子).[http://cocosbuilder.com/?page_id=11] 而CocosBuilder v3.0采用了一个叫做CocosDragonJS的例子, 主要是展示CocosBuilder 的Javascript的调用能力.我虽然很喜欢JS, 但是正在学习2d-x, 又很想学好, 所以还是打好基础, 学好原滋原味的2d-x才好, 以后换用无论是Html5, 还是JS, Lua, 心里才会觉得踏实.我无论C++,还是2d-x都是新手,又是第一次想正儿八经的写文章, 难免有很多错误, 还望各位看客踊跃拍砖.

对CocosBuilder不熟悉的朋友, 可以先去CocosBuilder网站看下其例子, 或者运行下cocos2d-x源代码目录下sample/TestCpp项目, 可以在ExtensionsTest里面找到CocosBuilderTest这个例子.

这次的目的是基本实现原来v2.0中的例子. 我采用的2d-x的版本是:cocos2d-2.1beta3-x-2.1.0, 以OS X版本为主, 以sample目录下的HelloCpp为基础改进. CocosBuilder 的版本是v3.0alpha0.

(一)
万事开头难,我们先来建立基本的开发环境, 保证最基本的运行.

我们需要一份cocos2d-2.1beta3-x-2.1.0的源代码, 并将其sample/HelloCpp目录重命名为sample/CocosBuilderTest. 打开CocosBuilder, 在sample/CocosBuilderTest/ccb-source/目录中创建一个新的CocosBuilder项目. 将CocosBuilder官方例子中的图片等资源文件复制到该目录. 我们对该目录下的文件结构做了一些调整, 以便于使用. 具体可以参见我打包后的整体项目文件.


我们可以在CocosBuilder菜单中找到Project/Publish Settings, 应该被设置成如图的样子.

这时我们可以Publish下项目, CocosBuilder会将ccb文件输出成二进制的ccbi文件,ccbi文件是我们在Xcode项目中使用的格式.

然后我们使用Xcode打开samples/CocosBuilderTest/proj.mac/HelloCpp.xcodeproj , 我们首先要将资源文件纳入项目. 然后再将cocos2d-x源码中的extensions目录也加入到项目中来, 其中负责ccbi文件解析的模块CCBReader即包含在该目录中.但并不是该目录所有文件都需要引入, 参见下图或者代码包.

1.添加一个新类MainScene如下
MainScene.h

 
 
  1. #ifndef __HelloCpp__MainScene__
  2. #define __HelloCpp__MainScene__
  3.  
  4. #include "cocos2d.h"
  5. #include "cocos-ext.h"
  6.  
  7. class MainScene
  8. : public cocos2d::CCLayer //从CCLayer派生
  9. {
  10. public:
  11. static cocos2d::CCScene* scene();
  12. };
  13.  
  14. #endif /* defined(__HelloCpp__MainScene__) */

MainScene.cpp

 
 
  1. #include "MainScene.h"
  2.  
  3. USING_NS_CC;
  4. USING_NS_CC_EXT;
  5.  
  6. CCScene* MainScene::scene()
  7. {
  8. CCScene *scene = CCScene::create();
  9.  
  10. CCNodeLoaderLibrary *lib = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary(); //生成一个默认的Node Loader
  11.  
  12. CCBReader *reader = new CCBReader(lib); //用node load lib 初始化一个ccb reader
  13.  
  14. CCNode *node = reader->readNodeGraphFromFile("MainScene.ccbi", scene); //从ccbi文件中加载node
  15.  
  16. reader->release(); //注意手动释放内存
  17.  
  18. if (node!=NULL)
  19. {
  20. scene->addChild(node); //将node 添加到scene中
  21. }
  22.  
  23. return scene;
  24. }

2.修改AppDelegate.cpp中默认的启动scene

 
 
  1. CCScene *pScene = MainScene::scene(); //HelloWorld::scene();

3.注意CocosBuilder 中发布选项的设置, 并发布一次.

4.如果没有错误的话, 你应该可以看到运行的效果.

需要说明的一点是CocosBuilder v3.0新增了一个自动缩放资源到匹配分辨率的功能. 我们这次没有使用该功能.

(二)
这一小节我们主要实现CocosBuilder官方例子中HelloCocosBuilder这一例子.

1
在CocosBuilder 中打开MainScene.ccb,按delete键删除已经存在的几个Sprite.

2
添加一个CCLayerGradient到屏幕, 如果有问题的话, 可以参见下CocosBuilder的帮助文档. 选中该节点, 我们可以在右侧看到他的属性, 常规的属性有比如位置, 大小, 锚点, 缩放, 旋转, 标签. 我们现在将其设置为大小为100%x100%的大小, 即满屏.

3
从左侧的文件列表中将burst.png拖入屏幕, 也可以使用工具栏添加然后再选择属性Sprite frame.
可以在节点树上双击该节点给其重命名, 我们将该节点命名为CCSprite-burst, 便于识别.
同样我们将其中心的设置到屏幕中心50%x50%, 缩放到2.5倍.
然后将Blend src, Blend dst 都设置为One, 好吧, 我暂时还不知道这个Blend是什么东西. 有知道的朋友不妨在评论中告诉我下, 或者参考资料.
大概是透明之类的东西吧.

4
然后我们再添加一个CCParticleSystemQuad粒子系统, 就是工具栏的那个Fx按钮.
将其位置设为最下居中, 在最下边Particle Texture设置为ccbParticleSnow.png效果,粒子系统还是很复杂的,估计能单独讲很久了. 这里就不再展开了.

5
将logo-icon.png拖入屏幕, 放在左上角合适位置, 并将其缩放到0.5. 节点重命名为CCSprite-logo-icon.
接下来就是动画的制作了.选中节点, 可以在菜单栏中Animation => Insert KeyFrame找到插入Framekey的各种快捷键.或许我们需要记熟他们.
首先让我们给Timeline设置下时间.双击时间可以编辑, 我们输入00:03:00, 就是3秒钟. 后面最后一位是帧数, 每秒30帧.
按下小三角可以展开当前节点的各种KeyFrame.
拖动时间轴游标到1秒10帧,按下键盘S, 可以插入一个Scale类型的KeyFrame, 这时将当前节点Scale属性改为0.
然后继续拖动时间轴游标到2秒10帧, 再插入一个Scale KeyFrame, 并将Scale属性改为0.5. 这时点击播放按钮, 可以看到logo会蹦出来.
然后在紫色条上点击右键, 可以看到动作菜单, 我们选择Bounce Out, 这个时候再点击播放, 就可以看到logo蹦出的时候会有一个弹震的效果.
再来说明两点, 紫色条设置不同的动作, 可以看到上面会有一点阴影变化, 可以帮助我们快速确认设置的是什么动作.
如果不小心加多了KeyFrame, 那么可以点击选择KeyFrame, 然后点击delete键删除.
还有需要注意的是, 如果游标不在KeyFrame的点上, 那么此时无法编辑该节点属性, 移动到相应的KeyFrame点即可.

6
然后依法炮制, 将logo.png加入, 你可以给其设置想要的动画效果.

7
我们再添加一个CCLabelBMFont, 字体设置为markerfelt24shadow.fnt.Label的内容设置为”Hello Cocos2d-x!!!”, 然后调整下位置, 换个喜欢的颜色.

8
我们再添加一个CCControlButton, Title设置为Menu & Item.
然后再分别设置State Normal, State Highlighted的Sprite frame为btn-test-0.png btn-test-1.png.
然后再设置下弹出效果.
将这个节点再复制5份, 对齐. 再分别设置下Title和弹出效果.设置对齐的时候可能会比较麻烦. 可以从标尺那里拉出几条线, 可以用于对齐.按下cmd键,将该对齐线拉出显示区域即可删除.

9
最后将左右的两片叶子加入屏幕, 设置个动画即可. 然后将CocosBuilder 项目发布一下, 在Xcode里面将项目运行一下. 就可以看到效果了.

10
我们接下来研究文件和类的绑定, 控件和变量的绑定, 以及事件和函数的绑定.
我们在CocosBuilder 中将根节点的Custom class设置为MainScene.
我们在Xcode中打开MainScene.h, 给MainScene增加一个新的函数CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(MainScene, create);.
最后的代码应该如下:

MainScene类

 
 
  1. class MainScene
  2. : public cocos2d::CCLayer
  3. {
  4. public:
  5. static cocos2d::CCScene* scene();
  6.  
  7. CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(MainScene, create);
  8. };

然后在MainScene.h中添加一个新类MainSceneLayerLoader代码如下:

 
 
  1. class MainSceneLayerLoader : public cocos2d::extension::CCLayerLoader
  2. {
  3. public:
  4. CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(MainSceneLayerLoader, loader);
  5. protected:
  6. CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(MainScene);
  7. };

如果需要探究的话, 可以点开相应的函数定义. 也都是些简单的工作.
吐槽下, 这些名字真的是太难记. 可能需要多熟悉下, 搞清楚其原理了才好.

然后我们在MainScene.cpp中添加一行注册将ccb文件和类绑定起来.

 
 
  1. CCNodeLoaderLibrary *lib = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();
  2. lib->registerCCNodeLoader("MainScene", MainSceneLayerLoader::loader());

然后运行下, 确保没有错误.
这几行代码, 就是ccb文件和类绑定的最简模式了.

11
接着我们研究下控件和变量的绑定.
我们先在CocosBuilder 中给CCLabelBMFont添加一个Doc root var类型的绑定mLabelText.
一个需要注意的地方就是CocosBuilder v3.0alpha似乎无法将jsControlled设置为false, 所以可能需要手工打开MainScene.ccb将其改为false.

MainScene.ccb

 
 
  1. jsControlled

然后在Xcode中给MainScene增加一个从CCBMemberVariableAssigner的继承并实现其虚函数. 并且添加相应的变量.

 
 
  1. class MainScene
  2. : public cocos2d::CCLayer
  3. , public cocos2d::extension::CCBMemberVariableAssigner
  4. {
  5. public:
  6. MainScene();
  7. ~MainScene();
  8.  
  9. static cocos2d::CCScene* scene();
  10.  
  11. CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(MainScene, create);
  12.  
  13. virtual bool onAssignCCBMemberVariable(cocos2d::CCObject* pTarget, const char* pMemberVariableName, cocos2d::CCNode* pNode);
  14.  
  15. private:
  16. cocos2d::CCLabelBMFont *mLabelText;
  17. };

在MainScene.cpp中需要添加的是:
MainScene.cpp

 
 
  1. MainScene::MainScene()//构造函数
  2. : mLabelText(NULL)
  3. {}
  4.  
  5. MainScene::~MainScene()//析构函数中释放内存不能忘
  6. {
  7. CC_SAFE_DELETE(mLabelText);
  8. }
  9.  
  10. bool MainScene::onAssignCCBMemberVariable(cocos2d::CCObject *pTarget, const char *pMemberVariableName, cocos2d::CCNode *pNode)
  11. {
  12. CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "mLabelText", CCLabelBMFont*, this->mLabelText);
  13.  
  14. return true;
  15. }

需要注意的是, 由于绑定较晚, 所以无法在init函数中使用变量mLabelText.

12
接下来我们研究事件和函数的绑定.
在CocosBuilder 中找到Menu & Item这个CCControlButton, 并设置其Selector为onButtonTest.Target设置为Document root.
这里需要注意的是, 设置值的时候,cocos2d-iphone似乎比较喜欢设置成onButtonTest:即多个:的形式. 我们在cocos2d-x中保持一致即可.不必加:.
然后打开MainScene.h给MainScene再增加一个继承.

MainScene

 
 
  1. class MainScene
  2. : public cocos2d::CCLayer
  3. , public cocos2d::extension::CCBMemberVariableAssigner
  4. , public cocos2d::extension::CCBSelectorResolver

还有需要实现的函数

 
 
  1. virtual cocos2d::SEL_MenuHandler onResolveCCBCCMenuItemSelector(cocos2d::CCObject * pTarget, const char* pSelectorName);
  2. virtual cocos2d::extension::SEL_CCControlHandler onResolveCCBCCControlSelector(cocos2d::CCObject * pTarget, const char* pSelectorName);
  3.  
  4. void onButtonTest(cocos2d::CCObject *pSender, cocos2d::extension::CCControlEvent pCCControlEvent);

接下来是增加的函数的实现
MainScene.cpp

 
 
  1. SEL_MenuHandler MainScene::onResolveCCBCCMenuItemSelector(cocos2d::CCObject *pTarget, const char *pSelectorName)
  2. {
  3. return NULL;
  4. }
  5.  
  6. SEL_CCControlHandler MainScene::onResolveCCBCCControlSelector(cocos2d::CCObject *pTarget, const char *pSelectorName)
  7. {
  8. CCB_SELECTORRESOLVER_CCCONTROL_GLUE(this, "onButtonTest", MainScene::onButtonTest);
  9.  
  10. return NULL;
  11. }
  12.  
  13. void MainScene::onButtonTest(cocos2d::CCObject *pSender, cocos2d::extension::CCControlEvent pCCControlEvent)
  14. {
  15. this->mLabelText->setString("Hello CocosBuilder!!!");
  16. }

好了, 现在运行一下, 点击按钮, 就会看到Hello Cocos2d-x!!!变成了Hello CocosBuilder!!!了.

13
刚才我们提到变量绑定较init函数(更别提运行更早的构造函数了)更晚. 那么如何运行后就控制这些控件呢?
方法当然是有, 我们需要增加一个CCNodeLoaderListener, 并实现其接口.新增代码如下:
MainScene

 
 
  1. , public cocos2d::extension::CCBSelectorResolver
  2. , public cocos2d::extension::CCNodeLoaderListener
  3. {
  4. ///......代码省略鸟
  5. virtual void onNodeLoaded(cocos2d::CCNode * pNode, cocos2d::extension::CCNodeLoader * pNodeLoader);
  6. ///......代码省略鸟
  7. }

MainScene.cpp

 
 
  1. void MainScene::onNodeLoaded(cocos2d::CCNode *pNode, cocos2d::extension::CCNodeLoader *pNodeLoader)
  2. {
  3. this->mLabelText->setString("All Loaded");
  4. }

好啦, 运行就能看到All Loaded啦.

(三)
这一节要说的内容比较轻松, 重要的知识点也不多.
目标是实现Menus & Items, Sprites & 9 Slice, Buttons & Labels.

1
首先我们在CocosBuilder中建立一个新的Header.ccb.具体请参见CocosBuilder的项目.
在创建的时候,勾选Full Sceen, 并且将分辨率的Height都修改为40.
这个文件很简单, 根节点下只包含一个CCLayerColor,根节点的Custom class设置为HeaderLayer.
CCLayerColor下面包含一个CCLabelTTF和CCMenu.
CCLabelTTF的变量绑定为类型Owner var, 值为mTitleLabelTTF.
CCMenu包含一个CCMenuItemImage. CCMenuItemImage的Selector属性设置为onBackClicked.
这个ccb作为一个公用的元素被其他ccb文件所引用. 是属于模块化的一个例子.
然后我们在Xcode中新建一个HeaderLayer类, 并同时声明一个HeaderLayerLoader类.

HeaderLayer.h

 
 
  1. class HeaderLayer
  2. : public cocos2d::CCLayer
  3. , public cocos2d::extension::CCBSelectorResolver
  4. {
  5. public:
  6. CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(HeaderLayer, create);
  7.  
  8. virtual cocos2d::SEL_MenuHandler onResolveCCBCCMenuItemSelector(CCObject * pTarget, const char* pSelectorName);
  9. virtual cocos2d::extension::SEL_CCControlHandler onResolveCCBCCControlSelector(CCObject * pTarget, const char* pSelectorName);
  10.  
  11. void onBackClicked(CCObject *pSender);
  12.  
  13. };
  14.  
  15. class HeaderLayerLoader : public cocos2d::extension::CCLayerLoader
  16. {
  17. public:
  18. CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(HeaderLayerLoader, loader);
  19. protected:
  20. CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(HeaderLayer);
  21. };

HeaderLayer.cpp

 
 
  1. SEL_MenuHandler HeaderLayer::onResolveCCBCCMenuItemSelector(cocos2d::CCObject *pTarget, const char *pSelectorName)
  2. {
  3. CCB_SELECTORRESOLVER_CCMENUITEM_GLUE(this, "onBackClicked", HeaderLayer::onBackClicked);
  4.  
  5. return NULL;
  6. }
  7.  
  8. SEL_CCControlHandler HeaderLayer::onResolveCCBCCControlSelector(cocos2d::CCObject *pTarget, const char *pSelectorName)
  9. {
  10. return NULL;
  11. }
  12.  
  13. void HeaderLayer::onBackClicked(cocos2d::CCObject *pSender)
  14. {
  15. CCDirector::sharedDirector()->popScene();
  16. }

2
在CocosBuilder中新建一个Menus.ccb, 并将根节点Custom class设置为MenuLayer.
再加入几个CCMenuItemImage, Selector分别设置为onPressA, onPressB, onPressC.
再加入一个CCLabelBMFont, 绑定Doc root var, 值为mMessageLabelBMFont.
在Xcode中新建一个类MenuLayer, 并且在MenuLayer.h中同时声明一个MenuLayerLoader类.

MenuLayer.h

 
 
  1. class MenuLayer
  2. : public cocos2d::CCLayer
  3. , public cocos2d::extension::CCBMemberVariableAssigner
  4. , public cocos2d::extension::CCBSelectorResolver
  5. {
  6. public:
  7. MenuLayer();
  8. ~MenuLayer();
  9.  
  10. CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(MenuLayer, create);
  11.  
  12. virtual bool onAssignCCBMemberVariable(CCObject* pTarget, const char* pMemberVariableName, CCNode* pNode);
  13. virtual cocos2d::SEL_MenuHandler onResolveCCBCCMenuItemSelector(CCObject * pTarget, const char* pSelectorName);
  14. virtual cocos2d::extension::SEL_CCControlHandler onResolveCCBCCControlSelector(CCObject * pTarget, const char* pSelectorName);
  15.  
  16. void onPressA(cocos2d::CCObject *pSender);
  17. void onPressB(cocos2d::CCObject *pSender);
  18. void onPressC(cocos2d::CCObject *pSender);
  19.  
  20. private:
  21. cocos2d::CCLabelBMFont *mMessageLabelBMFont;
  22. };
  23.  
  24. class MenuLayerLoader : public cocos2d::extension::CCNodeLoaderLibrary
  25. {
  26. public:
  27. CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(MenuLayerLoader, loader);
  28. protected:
  29. CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(MenuLayer);
  30. };

MenuLayer.cpp

 
 
  1. MenuLayer::MenuLayer()
  2. : mMessageLabelBMFont(NULL)
  3. {}
  4.  
  5. MenuLayer::~MenuLayer()
  6. {
  7. CC_SAFE_DELETE(mMessageLabelBMFont);
  8. }
  9.  
  10. bool MenuLayer::onAssignCCBMemberVariable(cocos2d::CCObject *pTarget, const char *pMemberVariableName, cocos2d::CCNode *pNode)
  11. {
  12. CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "mMessageLabelBMFont", CCLabelBMFont*, this->mMessageLabelBMFont);
  13. return false;
  14. }
  15.  
  16. SEL_MenuHandler MenuLayer::onResolveCCBCCMenuItemSelector(cocos2d::CCObject *pTarget, const char *pSelectorName)
  17. {
  18. CCB_SELECTORRESOLVER_CCMENUITEM_GLUE(this, "onPressA", MenuLayer::onPressA);
  19. CCB_SELECTORRESOLVER_CCMENUITEM_GLUE(this, "onPressB", MenuLayer::onPressB);
  20. CCB_SELECTORRESOLVER_CCMENUITEM_GLUE(this, "onPressC_NO_Match", MenuLayer::onPressC);
  21. //注意这里, 我们给第三个绑定了一个不存在的SelectorName.
  22. return NULL;
  23. }
  24.  
  25. SEL_CCControlHandler MenuLayer::onResolveCCBCCControlSelector(cocos2d::CCObject *pTarget, const char *pSelectorName)
  26. {
  27. return NULL;
  28. }
  29.  
  30. void MenuLayer::onPressA(cocos2d::CCObject *pSender)
  31. {
  32. this->mMessageLabelBMFont->setString("A pressed.");
  33. }
  34.  
  35. void MenuLayer::onPressB(cocos2d::CCObject *pSender)
  36. {
  37. this->mMessageLabelBMFont->setString("B pressed.");
  38. }
  39.  
  40. void MenuLayer::onPressC(cocos2d::CCObject *pSender)
  41. {
  42. this->mMessageLabelBMFont->setString("C pressed.");
  43. }

3
或许有点着急了吧, 我们如何让这个运行起来呢?
首先给MainScene增加一个新函数的声明及定义, 还需要增加一个变量用于和Header.ccb中的mTitleLabelTTF绑定.

MainScene.h

 
 
  1. public:
  2. void openTest(const char * pCCBFileName, const char * pCCNodeName = NULL, cocos2d::extension::CCNodeLoader * pCCNodeLoader = NULL);
  3. private:
  4. cocos2d::CCLabelTTF *mTitleLabelTTF;

MainScene.cpp

 
 
  1. void MainScene::openTest(const char * pCCBFileName, const char * pCCNodeName, cocos2d::extension::CCNodeLoader * pCCNodeLoader)
  2. {
  3. CCScene *scene = CCScene::create();
  4.  
  5. CCNodeLoaderLibrary *lib = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();
  6.  
  7. lib->registerCCNodeLoader("HeaderLayer", HeaderLayerLoader::loader());
  8. lib->registerCCNodeLoader(pCCNodeName, pCCNodeLoader);
  9.  
  10. CCBReader *reader = new CCBReader(lib);
  11. CCNode *node = reader->readNodeGraphFromFile(pCCBFileName, this);
  12. reader->autorelease();
  13.  
  14. if (node != NULL)
  15. {
  16. scene->addChild(node);
  17. }
  18.  
  19. this->mTitleLabelTTF->setString(pCCBFileName);
  20.  
  21. CCDirector::sharedDirector()->pushScene(scene);
  22. }
  23.  
  24. bool MainScene::onAssignCCBMemberVariable(cocos2d::CCObject *pTarget, const char *pMemberVariableName, cocos2d::CCNode *pNode)
  25. {
  26. CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "mLabelText", CCLabelBMFont*, this->mLabelText);
  27. CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "mTitleLabelTTF", CCLabelTTF*, this->mTitleLabelTTF);
  28.  
  29. return false;
  30. }
  31. void MainScene::onButtonTest(cocos2d::CCObject *pSender, cocos2d::extension::CCControlEvent pCCControlEvent)
  32. {
  33. this->openTest("ccb/Menus.ccbi", "MenuLayer", MenuLayerLoader::loader());
  34. }

运行一下吧, 看看效果.

4
Sprites & 9 Slice 这个比较简单, 只是靠CocosBuilder就能完成任务了.我这里就不在赘述了.

我拼的不太好, 嘿嘿. 主要是着重代码, 并非设计, 漂亮的事情交给美术妹纸吧.

5
Buttons这块主要是研究了CCControlEvent的各种情况. 我们只贴出核心代码.

ButtonsLayer.cpp

 
 
  1. void ButtonsLayer::onBtnClicked(cocos2d::CCObject *pSender, cocos2d::extension::CCControlEvent pCCControlEvent)
  2. {
  3. switch (pCCControlEvent) {
  4. case CCControlEventTouchCancel:
  5. this->mEventLabelBMFont->setString("Cancel");
  6. break;
  7. case CCControlEventTouchDown:
  8. this->mEventLabelBMFont->setString("Touch Down");
  9. break;
  10. case CCControlEventTouchDragEnter:
  11. this->mEventLabelBMFont->setString("Drag Enter");
  12. break;
  13. case CCControlEventTouchDragExit:
  14. this->mEventLabelBMFont->setString("Drag Exit");
  15. break;
  16. case CCControlEventTouchDragInside:
  17. this->mEventLabelBMFont->setString("Drag Inside");
  18. break;
  19. case CCControlEventTouchDragOutside:
  20. this->mEventLabelBMFont->setString("Drag OutSide");
  21. break;
  22. case CCControlEventTouchUpInside:
  23. this->mEventLabelBMFont->setString("Up Inside");
  24. break;
  25. case CCControlEventTouchUpOutside:
  26. this->mEventLabelBMFont->setString("Up Outside");
  27. break;
  28. default://所有的定义都在上面了,TestCPP里面有句经典的点评, 想看的可以去翻一下.
  29. break;
  30. }
  31. }

(四)
这一节也是很轻松, 主要是牵涉到Timeline的切换. 其他的都是简单的界面制作.
所以CocosBuilder的威力也体现在这里, 很少的代码就能驱动界面了.

我们这次先做Particle System, Scroll View, 最后以Animations收官.

1
制作Particle System和Scroll View的界面很简单,我们也是以程序为重点, 所以不再赘述.
只需要一句this->openTest(“ccb/Scroll.ccbi”);就可以调用新的界面了.
其他诸如绑定之类相信大家已经是轻车熟路啦.


2
好吧, 我承认一点, 制作Animations的界面的时候, 我直接复制了例子中的节点.
5个Timeline, 还是很复杂的, 应该是一个非常精细的工作. 向美术们致敬.

AnimationsLayer.h

 
 
  1. class AnimationsLayer
  2. : public cocos2d::CCLayer
  3. , public cocos2d::extension::CCBSelectorResolver
  4. {
  5. public:
  6. AnimationsLayer();
  7. ~AnimationsLayer();
  8.  
  9. CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(AnimationsLayer, create);
  10.  
  11. virtual cocos2d::SEL_MenuHandler onResolveCCBCCMenuItemSelector(CCObject * pTarget, const char* pSelectorName);
  12. virtual cocos2d::extension::SEL_CCControlHandler onResolveCCBCCControlSelector(CCObject * pTarget, const char* pSelectorName);
  13. void setAnimationManager(cocos2d::extension::CCBAnimationManager *pAnimationManager);
  14.  
  15. void onIdle(cocos2d::CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent);
  16. void onWave(cocos2d::CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent);
  17. void onJump(cocos2d::CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent);
  18. void onFunky(cocos2d::CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent);
  19. private:
  20. cocos2d::extension::CCBAnimationManager *mAnimationManager;
  21. };
  22.  
  23. class AnimationsLayerLoader : public cocos2d::extension::CCNodeLoader
  24. {
  25. public:
  26. CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(AnimationsLayerLoader, loader);
  27. protected:
  28. CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(AnimationsLayer);
  29. };

AnimationsLayer.cpp

 
 
  1. AnimationsLayer::AnimationsLayer()
  2. : mAnimationManager(NULL)
  3. {}
  4.  
  5. AnimationsLayer::~AnimationsLayer()
  6. {
  7. CC_SAFE_RELEASE_NULL(mAnimationManager);
  8. }
  9.  
  10. SEL_MenuHandler AnimationsLayer::onResolveCCBCCMenuItemSelector(cocos2d::CCObject *pTarget, const char *pSelectorName)
  11. {
  12. return NULL;
  13. }
  14.  
  15. SEL_CCControlHandler AnimationsLayer::onResolveCCBCCControlSelector(cocos2d::CCObject *pTarget, const char *pSelectorName)
  16. {
  17. CCB_SELECTORRESOLVER_CCCONTROL_GLUE(this, "onIdle", AnimationsLayer::onIdle);
  18. CCB_SELECTORRESOLVER_CCCONTROL_GLUE(this, "onJump", AnimationsLayer::onJump);
  19. CCB_SELECTORRESOLVER_CCCONTROL_GLUE(this, "onWave", AnimationsLayer::onWave);
  20. CCB_SELECTORRESOLVER_CCCONTROL_GLUE(this, "onFunky", AnimationsLayer::onFunky);
  21.  
  22. return NULL;
  23. }
  24.  
  25. void AnimationsLayer::setAnimationManager(cocos2d::extension::CCBAnimationManager *pAnimationManager)
  26. {
  27. CC_SAFE_RELEASE_NULL(mAnimationManager);
  28. mAnimationManager = pAnimationManager;
  29. CC_SAFE_RETAIN(mAnimationManager);
  30. }
  31.  
  32. void AnimationsLayer::onIdle(cocos2d::CCObject *pSender, cocos2d::extension::CCControlEvent pCCControlEvent)
  33. {
  34. this->mAnimationManager->runAnimationsForSequenceNamedTweenDuration("Idle", 0.3f);
  35. }
  36.  
  37. void AnimationsLayer::onJump(cocos2d::CCObject *pSender, cocos2d::extension::CCControlEvent pCCControlEvent)
  38. {
  39. this->mAnimationManager->runAnimationsForSequenceNamedTweenDuration("Jump", 0.3f);
  40. }
  41.  
  42. void AnimationsLayer::onWave(cocos2d::CCObject *pSender, cocos2d::extension::CCControlEvent pCCControlEvent)
  43. {
  44. this->mAnimationManager->runAnimationsForSequenceNamedTweenDuration("Wave", 0.3f);
  45. }
  46.  
  47. void AnimationsLayer::onFunky(cocos2d::CCObject *pSender, cocos2d::extension::CCControlEvent pCCControlEvent)
  48. {
  49. this->mAnimationManager->runAnimationsForSequenceNamedTweenDuration("Funky", 0.3f);
  50. }

整个代码还是很简单. 和以前的几个例子稍微有点不同的是在调用的时候, 需要把CCBReader里面的AnimationManger传入.
好, 还是看下调用的代码吧.

MainScene.cpp

 
 
  1. void MainScene::onAnimations(cocos2d::CCObject *pSender, cocos2d::extension::CCControlEvent pCCControlEvent)
  2. {
  3. const char * pCCBFileName = "ccb/Animations.ccbi";
  4. const char * pCCNodeName = "AnimationsLayer";
  5. cocos2d::extension::CCNodeLoader * pCCNodeLoader = AnimationsLayerLoader::loader();
  6.  
  7. CCScene *scene = CCScene::create();
  8.  
  9. CCNodeLoaderLibrary *lib = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();
  10.  
  11. lib->registerCCNodeLoader("HeaderLayer", HeaderLayerLoader::loader());
  12.  
  13. if (pCCNodeName!=NULL && pCCNodeLoader!=NULL)
  14. {
  15. lib->registerCCNodeLoader(pCCNodeName, pCCNodeLoader);
  16. }
  17.  
  18. CCBReader *reader = new CCBReader(lib);
  19. CCNode *node = reader->readNodeGraphFromFile(pCCBFileName, this);
  20. reader->autorelease();
  21.  
  22. if (node != NULL)
  23. {
  24. //获取AnimationManger 并传给AnimationsLayer
  25. ((AnimationsLayer*)node) ->setAnimationManager(reader->getAnimationManager());
  26.  
  27. scene->addChild(node);
  28. }
  29.  
  30. this->mTitleLabelTTF->setString(pCCBFileName);
  31.  
  32. CCDirector::sharedDirector()->pushScene(scene);
  33. }

后记
@王哲Walzer 说,CocosBuilder 大部分是美术在用, 在美术圈讨论, 所以程序圈较少看到人在讨论, 其实用的公司挺多的. http://weibo.com/1702027805/zay18wLT5

看到微博上@做游戏的老G 吐槽说CocosBuilder如何不好用, 学习难度比较大. 我也是很认可这一点.
但是只要是坚持把TestCpp例子完全读完了, 相信掌握CocosBuilder也是很快能够做到的.
既然你看完了这个教程. 相信你也已经能够很好地驾驭CocosBuilder. 关键还在实践呦!

微博上@Ghost_233 说了一个很好的思路, 直接从ccb文件中生成对应的C++类, 而且他还做了一些实践.
我暂时还没有研究他的代码, 不过肯定是可行. 这是一个很赞的思路.
希望大家能动手, 最好合作出来一个较好的工具来, 我想, 是不是集成到CocosBuilder会更好?

谢谢大家耐心看完我的文章.

希望能对您有些帮助.如果有什么问题, 意见, 建议, 拍砖, 欢迎留言或者联系我.

代码打包下载: http://pan.baidu.com/share/link?shareid=174299&uk=2281999082

新浪微博: @杨世玲 http://weibo.com/young40
Github Pages:http://young40.github.com/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值