Cocos2d-x
发布时间:2022-05-03 发布网站:大佬教程 code.js-code.com
大佬教程收集整理的这篇文章主要介绍了cocos2d-x学习笔记——cocos2d-x3.0回调函数的变化,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
原文转自Cocos2d-x 3.0 新特性体验(2) 回调函数的变化
在cocos2d-x 2.x版本中的回调函数的用法想必大家都很是熟悉,例如在menu item,call BACk action中都需要大量的使用到回调函数,但是在使用过程中总是感觉到比较冗余麻烦的,在3.0版本,使用到了C++11 的新特性,改进增加了回到函数的使用形式,其中最令人欣慰的是,可以使用闭包,对于有过iOS开发经验的来说,应该很亲切,就是 block。
下面将通过几个例子详细介绍在3.0版本中回调函数的各种用法。温馨提示:由于用到了C++11中的std::function,std::bind和lambda表达式,所以对此不太了解的可以先看看我之前的这篇有关C++11的一些用法介绍 点击打开链接。
一、通过 HelloWorldScene 中的 closeItem 开始
在cocos2d-x 2.x 版本中:
- CCMenuItemImage*pCloseItem=CCMenuItemImage::create(
- "CloseNormal.png",
- "CloseSELEcted.png",
- this,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> @H_888_53@menu_SELEctor(HelloWorld::menuCloseCallBACk));
在cocos2d-x 3.0 版本中:
autocloseItem=MenuItemImage::create(
- CC_CALLBACK_1(HelloWorld::menuCloseCallBACk,this));
voidHelloWorld::menuCloseCallBACk(Object*pSender)
- {
- Director::geTinstance()->end();
-
- #if(CC_TARGET_PLATFORM==CC_PLATFORM_IOS)
- exit(0);
- #endif
- }
注意到在3.0版本中使用到 CC_CALLBACK_1 这样一个宏定义。
- #defineCC_CALLBACK_0(__SELEctor__,__target__,...)std::bind(&__SELEctor__,##__VA_ARGS__)
- #defineCC_CALLBACK_1(__SELEctor__,std::placeholders::_1,##__VA_ARGS__)
- #defineCC_CALCC_CALLBACK_1(HelloWorld::menuCloseCallBACk,this)LBACK_2(__SELEctor__,std::placeholders::_2,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> #defineCC_CALLBACK_3(__SELEctor__,std::placeholders::_3##__VA_ARGS__)
原来还有 CC_CALLBACK_0 1 2 3;而其中又有什么区别呢?
1、首先我们看看3.0版本中MenuItemImage的create方法:
@H_993_54@menuItemImage*MenuItemImage::create(conststd::string&normalImage,conststd::string&SELEctedImage,153); BACkground-color:inherit; font-weight:bold">constccMenuCallBACk&callBACk)
其中的回调参数是 ccMenuCallBACk
typedefstd::function<void(Object*)>ccMenuCallBACk
原来这里使用到了 C++ 中的 function 语法。
注意到 在CC_CALLBACK_ 的宏定义的中使用到的是 C++ 的 bind 语法,怎么不一致了呢?-- 见下面第四点 function
2、看回CC_CALLBACK_ 的宏定义
原来CC_CALLBACK_ 的宏定义中后面的 0 1 2 3分别表示的是 不事先指定回调函数参数的个数。
例如说CC_CALLBACK_ 1 表示的是,回调函数中不事先指定参数是一个,而事先指定的回调函数的参数 可以任意多个。
而且要注意到其中 不指定回调函数参数 和 指定回调函数参数 的顺序,注意不事先指定的在前,事先指定的在后。
下面通过例子说明这一点:
假设回调函数:
//aSELEctorcallBACk
- void@H_993_54@menuCloseCallBACk(Object*pSender,inta,87); BACkground-color:inherit; font-weight:bold">intb);
voidHelloWorld::menuCloseCallBACk(Object*pSender,87); BACkground-color:inherit; font-weight:bold">intb)
- std::cout<<a<<""<<b<<std::endl;
- Director::geTinstance()->end();
-
- #if(CC_TARGET_PLATFORM==CC_PLATFORM_IOS)
- exit(0);
- #endif
- }
注意到在回调函数中输出 a b
BACkground-color:rgb(255,1,2));
注意中其中 指定了两个参数 1 2
运行,在 点击closeItem 的时候,就会输出这两个事先指定的参数 1 2。
那么,不事先指定的参数是在什么时候传入的呢?
void@H_993_54@menuItem::activate()
- if(_enabled)
- if(_callBACk)
- _callBACk(this);
- }
- if(kScriptTypeNone!=_scriptTypE)
- {
- BasicScriptDatadata(this);
- ScriptEventscriptEvent(kMenuClickedEvent,&data);
- ScriptENGIneManager::geTinstance()->getScriptENGIne()->sendEvent(&scriptEvent);
- }
- }
注意到其中的 _callBACk(this); 对了,这个时候就传入了 这个不事先指定的回调函数参数。
这样,closeItem 的回调函数的void HelloWorld::menuCloseCallBACk(Object* pSender,int a,int b) 的三个参数都知道了。
第一个 不事先指定,在menu item调用 activate 的时候,_callBACk(this) 传入,this 也即是这个 menu item;第二、三个参数是事先指定的 1,2。
3、bind
已经知道CC_CALLBACK_ 的宏定义是 std::bind 那么我们可以直接使用std::bind。
如下:
std::bind(&HelloWorld::menuCloseCallBACk,2));
4、function
最后就解决上面的一个疑惑。
std::function<void(Object*)>func=std::bind(&HelloWorld::menuCloseCallBACk,2);
- autocloseItem=MenuItemImage::create(
- "CloseNormal.png",248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> "CloseSELEcted.png",108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> func);
5、使用lambda表达式
[&](Object*sender){
- });
可见使用lambda表达式可以极大的简化代码程序,不需要再定义一个回调函数,直接将在回调中的操作在闭包中体现即可。
二、在cocos2d-x中,还有一个地方是需要大量使用到回调函数的,这就是回调动作:CCCallFunc、CCCallFuncN、CCCallFuncND、CCCallFuncO。
但是这四个回调动作在 3.0 版本中已经都提示 deprecate 了。那么在3.0 版本中已经只剩下CallFunc 和 CallFuncN.
下面是官方文档中的说明:
- @H_398_696@CallFunccan be created with an
std::function<void()>
CallFuncN
can be created with anstd::function<void(Node*)>
CallFuncND
andCallFuncO
were removed since it can be created with simulated withCallFuncN
andCallFunc
. See ActionsTest.cpp for more examples
其中:CallFuncND 和 CallFuncO 都可以通过CallFunc 和 CallFuncN 进行实现。
下面通过例子详细的介绍这两个回调动作的用法。
1、CallFunc
staticCallFunc*create(conststd::function<void()>&func);
关于CallFunc的例子,在文档中已经有体现:
//inv2.1
- CCCallFunc*action1=CCCallFunc::create(:rgb(0,callfunc_SELEctor(MyClass::callBACk_0));
-
- autoaction1=CallFunc::create(CC_CALLBACK_0(MyClass::callBACk_0,153); BACkground-color:inherit; font-weight:bold">this));
- autoaction2=CallFunc::create(CC_CALLBACK_0(MyClass::callBACk_1,additional_parameters));
- //inv3.0(longversion)
- autoaction1=CallFunc::create(std::bind(&MyClass::callBACk_0,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> autoaction2=CallFunc::create(std::bind(&MyClass::callBACk_1,0); BACkground-color:inherit">//inv3.0youcanalsouselambdasoranyother"Function"object
- autoaction1=CallFunc::create(
- [&](){
- autos=Director::sharedDirector()->getWinSize();
- autolabel=LabelTTF::create("called:lambdacallBACk","MarkerFelt",16);
- label->setPosition(ccp(s.width/4*1,s.height/2-40));
- this->addChild(label);
- });
2、CallFuncN
staticCallFuncN*create(void(Node*)>&func);
注意到该回调动作带有一个Node*参数。
假设回调函数:
voidActionCallFuncN::callBACk(Node*sender)
autoaction=Sequence::create(
- @H_888_53@moveBy::create(2.0f,Point(150,0)),
- CallFuncN::create(CC_CALLBACK_1(ActionCallFuncN::callBACk,153); BACkground-color:inherit; font-weight:bold">this)),248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> null);
CallFuncN::create(std::bind(&ActionCallFuncN::callBACk,std::placeholders::_1)),160); text-decoration:none; BACkground-color:inherit; border:none; padding:1px; margin:0px 10px 0px 0px; font-size:9px; display:inline-block; width:16px; height:16px" rel="nofollow">
CallFuncN::create([&](Node*sender){
- //回调动作代码
- }),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> null);
受益于C++11的新语法特性 std::bind ;
CallFuncND 和 CallFuncO 都可以通过
CallFunc 和 CallFuncN 进行实现
3、CallFuncND :回调动作中带有一个Node*参数和一个void*参数
实现过程类似于CallFuncN
假设回调函数是 :void ActionCallFuncND::doRemoveFromParentAndCleanup(Node* sender,bool cleanup)
那么在回调动作中:
CallFuncN::create( CC_CALLBACK_1(ActionCallFuncND::doRemoveFromParentAndCleanup,this,truE))
这样就实现了等价于CallFuncND 的回调动作。
4、CallFuncO :回调动作中带有一个Object*参数
实现过程类似于CallFunc
假设回调函数是:void ActionCallFuncO::callBACk(Node* node,bool cleanup)
那么在回调动作中:
CallFunc::create( CC_CALLBACK_0(ActionCallFuncO::callBACk,_grossini,truE)
这样就实现了等价于CallFuncO 的回调动作。
三、总结
在新版的回调处理中,采用了C++11中的 std::function 、std::bind 、lambda 表达式,使得回调的处理变得形式多样,代码灵活了,而其中的lambda表达式可以极大的简化回调代码,推荐使用。
原文转自Cocos2d-x 3.0 新特性体验(2) 回调函数的变化
大佬总结
以上是大佬教程为你收集整理的cocos2d-x学习笔记——cocos2d-x3.0回调函数的变化全部内容,希望文章能够帮你解决cocos2d-x学习笔记——cocos2d-x3.0回调函数的变化所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。