Cocos2d-x CocosBuilder使用教程(二)连接自定义类

简介: 本教程基于Cocos2d-x 2.0.4版本看来2013年2月最多只能写三篇技术博客了!今天学习使用了一下CocosBuilder的连接到自定义类的功能,确实很爽,让IOS的程序员们不必再硬编码了。

本教程基于Cocos2d-x 2.0.4版本

看来2013年2月最多只能写三篇技术博客了!今天学习使用了一下CocosBuilder的连接到自定义类的功能,确实很爽,让IOS的程序员们不必再硬编码了。通过看Cocosbuilder本身的document,以及搜索网上资料,加上自己查看CCB源码,完成连接自定义类的功能。首先需要注意一点,CocosBuilder的Document是针对Cocos2d-iPhone的而不是Cocos2d-x的,所以很多Document里面讲到的并不适用于Cocos2d-x。因为cocos2d-x是基于C++的,所以无法通过类名字符串来动态创建类(OC当然可以了),这也是为什么Cocos2d-x版本的CCB SDK在架构上添加CCNodeLoadLibrary的原因。

下面我将一步一步操作,并讲解其中原理,让你不但学会怎么做,而且还知其原理。

  1. 使用CocosBuilder 2.1版本新建一个Project,叫做“ConnectToCustomClass”(引号当然不算名称了,:p)。

  2. 新建一个文件,派生自CCLayer,并选择你想要的设备类型,我选择ipad landscape 1024 * 768,保存为“ConnectToCustomClass”(与项目工程一致)。

  3. 添加一个CCMenu节点到根节点(即CCLayer节点)。

  4. 添加一个CCMenuImage节点到CCMenu节点。
    选中此节点,到CocosBuilder右侧的CCMenuItemImage段中,点击Normal和Selected字段,选择对应图片(Disable不用的话可以不选择)。读者可以下载下列资源:
    Normal:
    Selected:

  5. 添加一个CCControlButton到根节点(即CCLayer节点)。
    选择此节点,到CocosBuilder右侧的CCControlButton段更改“Font Size”字段为15。这里使用CCControlButton也是为了让读者知道CocosBuilder中能处理按键消息的节点除了CCMenuItemImage以外,还有CControlButton。

  6. 添加一个CCLabelTTF到根节点(即CCLayer节点)。
    选择此节点,到CocosBuilder右侧的CCLabelTTF段更改“Font Size”字段为15。这里使用CCLabelTTF主要是教授如何在自定义的Layer类中声明一个CCLabelTTF*变量指向CocosBuilder界面中的CCLabelTTF节点。

  7. 界面布局如图。


  8. 界面的“皮”做完了,但界面的神经还没有接好。现在我们开始连接好界面的各个神经。

  9. 点击根节点(即CCLayer节点),在CocosBuilder右侧我们可以看到Code Connections段。我们将"XJLayer"填入其中的“Custom class”字段中。
    XJ是本人名称缩写,你可以写成自己的名称缩写(但后续操作中XJ要替换成你的名称前缀了)。此操作的含义:让CocosBuilder在保存此节点时,将其节点标签保存为“XJLayer”,这样在文件解析的时候,当我们碰到节点标签是"XJLayer"时,我们就知道这是我们自定义的XJLayer节点,我们需要对这个节点做特殊处理。

  10. 点击”切换账号“节点(CCMenuItemImage节点),在CocosBuilder右侧CCMenuItem段中,将”menuSelectorChangeAccount"填入“Selector“字段。在”Target“字段中选择”Document root“。如下图:

    看到这个,如果你编写过Cocos2d-x的CCMenuItem相关的代码,你应该很熟悉,这里的”Target“字段就是指的希望处理该消息事件的对象,这里是Document root,就是指的根节点,即我们的CCLayer节点(此节点Custom Class字段已经被我们改成”XJLayer“)。”Selector“字段就是处理消息事件的函数名称。

  11. 点击”Title“节点(CCControlButton节点),在CocosBuilder右侧CCControl段中,我们将”controlButtonTest“填入”Selector“字段,在”Target“字段中选择”Document root“。
    两个字段含义想必你能猜到。这里值得注意的是下面的9个复选框,这里默认选中”Up inside“。这些复选框表示你感兴趣的消息。当前你只对按键在button中抬起事件感兴趣。即:当用户点击此按钮抬起时,你的”controlButtonTest“函数会被调用(controlButtonTes函数在哪呢,后面会提到)。

  12. 点击”Sample Test“节点,在CocosBuilder右侧"Code Connections"字段,更改”Don't assign“字段为”Doc root var“字段,并将"m_TestLabel"填入该字段。
    这里是说,这个对象会被赋值给”文档根变量“,也就是根节点对象。赋给该对象的”m_TestLabel“成员变量。这里就是教授如何把CocosBuilder文件里的对象赋值给自定义类的某个成员变量,建立起Cocos2d-x和CocosBuilder的联系。

  13. 保存文件(【Command】+【s】,一定要保存文件哦,没有点击保存文件,更改不会被记录),然后发布(【Command】+【Option】+【S】)。

  14. 创建一个Cocos2d-x模版工程,起名叫做”ConnectToCustomLayer“。

  15. 从CocosBuilder创建的Project路径里面,将ccbResources文件夹(CCControlButton默认背景图片是在ccbResources文件夹下的),以及两张我提供的图片资源和一个”ConnectToCustomClass.ccbi“文件(不是ccb文件哦)拷贝到Cocos2d-x项目工程resources文件夹下,并全部添加到xCode项目的Resources下(注意,一定要添加到项目工程,这样加载ccbi文件时,CCB SDK才能找到ccbi文件。在添加的时候填出的提示框中,一定要选中对应目标项目即Target)。


  16. 在项目文件视图中,点击Classes,创建一个C++类【Command】+【N】。其名称叫做”XJLayer"。代码人如下:
    //
    //  XJLayer.h
    //  ConnectToCustomClass
    //
    //  Created by jason on 13-2-28.
    //
    //
    
    #ifndef __ConnectToCustomClass__XJLayer__
    #define __ConnectToCustomClass__XJLayer__
    
    
    #include "cocos2d.h"
    #include "cocos-ext.h"
    USING_NS_CC;
    USING_NS_CC_EXT;
    
    class XJLayer : public CCLayer, public CCBSelectorResolver, public CCBMemberVariableAssigner
    {
    	//static
    public:
    	CREATE_FUNC( XJLayer );
    	
    public:
            ~XJLayer()
    	{
    	    CC_SAFE_RELEASE_NULL( m_TestLabel );
    	}
    	void menuSelectorChangeAccount( CCObject* node );
    	void controlButtonTest(CCObject* pObject, CCControlEvent event);
    	
    	//CCBSelectorResolver
    	virtual SEL_MenuHandler onResolveCCBCCMenuItemSelector(CCObject * pTarget, CCString * pSelectorName);
        virtual extension::SEL_CCControlHandler onResolveCCBCCControlSelector(CCObject * pTarget, CCString * pSelectorName);
    	
    	//CCBMemberVariableAssigner
    	virtual bool onAssignCCBMemberVariable(CCObject * pTarget, CCString * pMemberVariableName, CCNode * pNode);
    	
    private:
    	CCLabelTTF* m_TestLabel;
    };
    
    class XJLayerLoader : public CCLayerLoader{
    public:
    	//CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD( XJLayerLoader, loader );
    	//				||(equal)
    	//	static XJLayerLoader* loader()
    	//	{
    	//		XJLayerLoader * ptr = new XJLayerLoader();
    	//		if(ptr != NULL) { 
    	//			ptr->autorelease();
    	//			return ptr; 
    	//		}
    	//		CC_SAFE_DELETE(ptr); 
    	//		return NULL;
    	//	}
    	CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD( XJLayerLoader, loader );
    	
    	//CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD( XJLayer );
    	//				||(equal)
    	//	virtual XJLayer * createCCNode(cocos2d::CCNode * pParent, cocos2d::extension::CCBReader * pCCBReader)
    	//	{
    	//		return XJLayer::create();
    	//	}
    
    	CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD( XJLayer );
    };
    
    
    #endif /* defined(__ConnectToCustomClass__XJLayer__) */
    

    代码是重点。
    1.这里XJLayer除了继承自CCLayer,也继承自两个你很陌生的类(CCBSelectorResolver,CCBMemberVariableAssigner)。通过字面意思,我们大体能知道,两个类分别是:selector解析器,和成员变量赋值器。这是两个抽象类,在java也称为接口。即继承自这两个类的类,必须重写其纯虚函数。
    CCBSelectorResolver有两个:
    virtual SEL_MenuHandler onResolveCCBCCMenuItemSelector(CCObject * pTarget, CCString * pSelectorName);
    virtual extension::SEL_CCControlHandler onResolveCCBCCControlSelector(CCObject * pTarget, CCString * pSelectorName);
    CCBMemberVariableAssigner有一个:
    virtual bool onAssignCCBMemberVariable(CCObject * pTarget, CCString * pMemberVariableName, CCNode * pNode);

    CCBSelectorResolver中分别解析MenuItem的消息处理函数和CControlButton的消息处理函数。
    CCBMemberVariableAssigner就是连接ccbi文件创建的对象与cocos2d-x对象的。

    另外:一定要施放与CocosBuilder绑定的对象。CC_SAFE_RELEASE_NULL( m_TestLabel );

    2.我们创建了一个XJLayerLoader,其继承自CCLayerLoader(CCLayerLoader是CCBReader中的一个类,此类负责CCLayer节点的加载)。通过派生,我们让这个加载器创建我们自己的类对象,也就是通过这个宏定义完成的——CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD( XJLayer );ccbi文件解析时,创建节点就是通过createCCNode完成的。我们会声明一个XJLayerLoader对象,传给ccbi阅读器,阅读器在特定时候调用该加载器的createCCNode()来创建我们自己的Layer。


    //
    //  XJLayer.cpp
    //  ConnectToCustomClass
    //
    //  Created by jason on 13-2-28.
    //
    //
    
    #include "XJLayer.h"
    
    void XJLayer::menuSelectorChangeAccount( CCObject* pObject )
    {
    	CCLog( "CGStartGameLayer::menuSelectorChangeAccount" );
    }
    void XJLayer::controlButtonTest(CCObject* pObject, CCControlEvent event)
    {
    	CCLog( "CGStartGameLayer::controlButtonEventhandle" );
    }
    
    SEL_MenuHandler XJLayer::onResolveCCBCCMenuItemSelector(CCObject * pTarget, CCString * pSelectorName)
    {
    	CCB_SELECTORRESOLVER_CCMENUITEM_GLUE( this, "menuSelectorChangeAccount", XJLayer::menuSelectorChangeAccount);
    	
    	return NULL;
    }
    
    extension::SEL_CCControlHandler XJLayer::onResolveCCBCCControlSelector(CCObject * pTarget, CCString * pSelectorName)
    {
    	CCB_SELECTORRESOLVER_CCCONTROL_GLUE( this, "controlButtonMoreServers", XJLayer::controlButtonTest );
    	return NULL;
    }
    
    bool XJLayer::onAssignCCBMemberVariable(CCObject * pTarget, CCString * pMemberVariableName, CCNode * pNode)
    {
    	CCB_MEMBERVARIABLEASSIGNER_GLUE( this, "m_TestLabel", CCLabelTTF*, m_TestLabel );
    	return false;
    }
    这里是两个消息处理函数,输出一些调试信息,以让我们知道按钮被点击了。另外三个函数,就是上面提到的三个虚函数,分别解决MenuItem消息处理函数归属(即那个函数作为消息处理函数),CControlButton消息处理函数归属,以及变量复制的。也分别对应三个宏,读者可以自己去看宏定义函数。

  17. 打开AppDelegate.cpp文件,做如下修改:
    #include "cocos-ext.h"
    #include "XJLayer.h"
    USING_NS_CC_EXT;

    cocs-ext.h包含了读取ccbi所需类的所有头文件。

    修改AppDelegate::applicationDidFinishLaunching()
    bool AppDelegate::applicationDidFinishLaunching()
    {
        // initialize director
        CCDirector *pDirector = CCDirector::sharedDirector();
        pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());
    
        // turn on display FPS
        pDirector->setDisplayStats(true);
    
        // set FPS. the default value is 1.0/60 if you don't call this
        pDirector->setAnimationInterval(1.0 / 60);
    
        // create a scene. it's an autorelease object
    //    CCScene *pScene = HelloWorld::scene();
    	
        CCNodeLoaderLibrary::sharedCCNodeLoaderLibrary()->registerCCNodeLoader( "XJLayer", XJLayerLoader::loader());
        CCBReader* reader = new CCBReader( CCNodeLoaderLibrary::sharedCCNodeLoaderLibrary() );
        reader->autorelease();
    	
        // run
        pDirector->runWithScene( reader->createSceneWithNodeGraphFromFile( "ConnectToCustomClass.ccbi" ) );
    
        return true;
    }
    CCNodeLoaderLibrary类内包含了所有节点的加载器。CCBReader类将使用这个库内的对应加载器去创建对应的节点。因为我们要创建我们自定义的节点,所以我们往库内注册了一个新节点加载器。
    CCNodeLoaderLibrary::sharedCCNodeLoaderLibrary()->registerCCNodeLoader( "XJLayer", XJLayerLoader::loader());
    即当遇到节点类型(或称为标签)为“XJLayer“的时候,使用XJLayerLoader::loader()创建出来的那个加载器来创建节点。而我们知道这个加载器重写createCCNode,这样就能正确创建出我们自定义的XJLayer了。

    另外当CCBReader遇到某些节点中有selector,target属性时,就会找到根节点(根节点就是我们的XJLayer节点,我们的加载器此时已经创建了一个XJLayer对象),然后调用对应的虚函数,去解决消息处理函数归属和变量复制的问题。这样就完成ccbi对象与cocos2d-x对象的连接。

  18. 运行程序,【Command】+【R】。如果顺利的话,你将得到如下运行效果:

    点击左侧两个按钮,xCode调试输出窗口内会有我们事先写入的调试信息输出。断点调试,你会发现XJLayer类对象的m_TestLabel是有值的。这就证明m_TestLabel正确连接了”Sample Test“标签。
写了快2个小时了好像,终于搞定,希望大家多交流,促进行业发展。

相关文章
|
4月前
|
存储 数据安全/隐私保护 C++
C++零基础教程(C++的类2)
C++零基础教程(C++的类2)
27 0
|
4月前
|
编译器 C++
C++零基础教程(C++中的类1)
C++零基础教程(C++中的类1)
37 0
|
4月前
|
存储 数据安全/隐私保护 C++
C++零基础教程(C++中的类)
C++零基础教程(C++中的类)
28 0
|
Java 程序员
Java面向对象8——接口(内含IDEA中有关创建接口的创建说明)
上一次我们说了抽象方法的存在是因为父类可以抽取子类中的共性方法,但是共性方法内实现方法不同所以要将共性方法写成抽象方法,那么如果子类中有一个“另类”不需要这个方法的话,我们就无法使用抽象方法了,而是要使用接口,哪个子类需要用,就继承该接口
235 0
Java面向对象8——接口(内含IDEA中有关创建接口的创建说明)
|
Java Android开发 Kotlin
Kotlin练手,以登录为例,Anko简单使用
Kotlin练手,以登录为例,Anko简单使用
216 0
Kotlin练手,以登录为例,Anko简单使用
|
存储 JSON API
Qt开发技术:Qt的动态静态插件框架介绍和Demo
Qt开发技术:Qt的动态静态插件框架介绍和Demo
Qt开发技术:Qt的动态静态插件框架介绍和Demo
|
编译器 开发工具 C语言
Qt编写自定义控件插件开放动态库dll使用(永久免费)
一、前言 这套控件陆陆续续完善了四年多,目前共146个控件,除了十几个控件参考网友开源的代码写的,其余全部原创,在发布之初就有打算将动态库开放出来永久免费使用,在控件比较完善的今天抽了半天时间编译了多个qt版本的动态库,目前已经有26个版本,其中包括了linux版本,和头文件一起打包放在百度网盘。
2448 0
|
存储 数据库 数据安全/隐私保护
MFC应用程序编写实例—完整版(原创)
前段时间,将近花了一周至两周上班和上班后的闲余时间,做了一个用于调试和测试工作项目的应用软件,下面将实现软件的重要步骤及主要功能讲解一遍,方便日后查阅。 程序开始后,提示登录框,输入用户名,密码后,登录进去主窗体,效果图如下:   下面将主要实现的功能函数要点进行描述,具体实现如下:  ...
1045 0
|
Android开发
GEF入门实例_总结_01_教程、源码、开发环境准备
一、前言 最近在学Eclipse插件开发,发现了一个比较好的GEF入门教程,并且按照教程上的操作,一步步实现了一个入门Demo,在此感谢作者的贡献。 好记性不如烂笔头,故决定总结一下这段时间的学习心得。
1460 0

热门文章

最新文章