在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 版本中:
1
2
3
4
5
|
CCMenuItemImage *pCloseItem = CCMenuItemImage::create( "CloseNormal.png" ,
"CloseSelected.png" ,
this ,
menu_selector(HelloWorld::menuCloseCallback));
|
在cocos2d-x 3.0 版本中:
1
2
3
4
|
auto closeItem = MenuItemImage::create( "CloseNormal.png" ,
"CloseSelected.png" ,
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this ));
|
1
2
3
4
5
6
7
8
|
void HelloWorld::menuCloseCallback(Object* pSender)
{ Director::getInstance()->end();
# if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit( 0 );
#endif } |
注意到在3.0版本中使用到 CC_CALLBACK_1 这样一个宏定义。
1
2
3
4
5
|
// new callbacks based on C++11 #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__) #define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__) #define CC_CALCC_CALLBACK_1(HelloWorld::menuCloseCallback, this )LBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3 ##__VA_ARGS__) |
原来还有 CC_CALLBACK_0 1 2 3;而其中又有什么区别呢?
1、首先我们看看3.0版本中MenuItemImage的create方法:
1
|
MenuItemImage * MenuItemImage::create( const std::string& normalImage, const std::string& selectedImage, const ccMenuCallback& callback)
|
其中的回调参数是 ccMenuCallback
1
|
typedef std::function< void (object*)> ccMenuCallback</ void (object*)>
|
原来这里使用到了 C++ 中的 function 语法。
注意到 在 CC_CALLBACK_ 的宏定义的中使用到的是 C++ 的 bind 语法,怎么不一致了呢? -- 见下面第四点 function
2、看回 CC_CALLBACK_ 的宏定义
原来 CC_CALLBACK_ 的宏定义中后面的 0 1 2 3分别表示的是 不事先指定回调函数参数的个数。
例如说 CC_CALLBACK_ 1 表示的是,回调函数中不事先指定参数是一个,而事先指定的回调函数的参数 可以任意多个。
而且要注意到其中 不指定回调函数参数 和 指定回调函数参数 的顺序,注意不事先指定的在前,事先指定的在后。
下面通过例子说明这一点:
假设回调函数:
1
2
|
// a selector callback void menuCloseCallback(Object* pSender, int a, int b);
|
1
2
3
4
5
6
7
8
|
void HelloWorld::menuCloseCallback(Object* pSender, int a, int b)
{ std::cout<end();
# if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit( 0 );
#endif }</a<<"> |
注意到在回调函数中输出 a b
1
2
3
4
|
auto closeItem = MenuItemImage::create( "CloseNormal.png" ,
"CloseSelected.png" ,
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this , 1 , 2 ));
|
注意中其中 指定了两个参数 1 2
运行,在 点击closeItem 的时候,就会输出这两个事先指定的参数 1 2。
那么,不事先指定的参数是在什么时候传入的呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
void MenuItem::activate()
{ if (_enabled)
{
if ( _callback )
{
_callback( this );
}
if (kScriptTypeNone != _scriptType)
{
BasicScriptData data( this );
ScriptEvent scriptEvent(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。
如下:
1
2
3
4
|
auto closeItem = MenuItemImage::create( "CloseNormal.png" ,
"CloseSelected.png" ,
std::bind(&HelloWorld::menuCloseCallback, this ,std::placeholders::_1, 1 , 2 ));
|
4、function
最后就解决上面的一个疑惑。
1
2
3
4
5
6
|
std::function< void (object*)> func = std::bind(&HelloWorld::menuCloseCallback, this , std::placeholders::_1, 1 , 2 );
auto closeItem = MenuItemImage::create(
"CloseNormal.png" ,
"CloseSelected.png" ,
func);
</ void (object*)>
|
5、使用lambda表达式
1
2
3
4
5
6
7
8
9
|
auto closeItem = MenuItemImage::create( "CloseNormal.png" ,
"CloseSelected.png" ,
[&](Object *sender){
Director::getInstance()->end();
# if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit( 0 );
#endif
});
|
可见使用lambda表达式可以极大的简化代码程序,不需要再定义一个回调函数,直接将在回调中的操作在闭包中体现即可。
二、在cocos2d-x中,还有一个地方是需要大量使用到回调函数的,这就是回调动作:CCCallFunc、CCCallFuncN、CCCallFuncND、CCCallFuncO。
但是这四个回调动作在 3.0 版本中已经都提示 deprecate 了。那么在3.0 版本中已经只剩下CallFunc 和 CallFuncN.
下面是官方文档中的说明:
-
CallFunc
can be created with anstd::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
1static
CallFunc * create(
const
std::function<
void
()>& func);</
void
()>
关于CallFunc的例子,在文档中已经有体现:
12345678910111213141516171819// in v2.1
CCCallFunc *action1 = CCCallFunc::create(
this
, callfunc_selector( MyClass::callback_0 ) );
// in v3.0 (short version)
auto action1 = CallFunc::create( CC_CALLBACK_0(MyClass::callback_0,
this
));
auto action2 = CallFunc::create( CC_CALLBACK_0(MyClass::callback_1,
this
, additional_parameters));
// in v3.0 (long version)
auto action1 = CallFunc::create( std::bind( &MyClass::callback_0,
this
));
auto action2 = CallFunc::create( std::bind( &MyClass::callback_1,
this
, additional_parameters));
// in v3.0 you can also use lambdas or any other "Function" object
auto action1 = CallFunc::create(
[&](){
auto s = Director::sharedDirector()->getWinSize();
auto label = LabelTTF::create(
"called:lambda callback"
,
"Marker Felt"
,
16
);
label->setPosition(ccp( s.width/
4
*
1
,s.height/
2
-
40
));
this
->addChild(label);
} );
2、CallFuncN
1static
CallFuncN * create(
const
std::function<
void
(node*)>& func);</
void
(node*)>
注意到该回调动作带有一个Node*参数。
假设回调函数:
1void
ActionCallFuncN::callback(Node* sender )
1234auto action = Sequence::create(
MoveBy::create(
2
.0f, Point(
150
,
0
)),
CallFuncN::create( CC_CALLBACK_1(ActionCallFuncN::callback,
this
)),
NULL);
1234auto action = Sequence::create(
MoveBy::create(
2
.0f, Point(
150
,
0
)),
CallFuncN::create(std::bind(&ActionCallFuncN::callback,
this
,std::placeholders::_1)),
NULL);
1234567auto action = Sequence::create(
MoveBy::create(
2
.0f, Point(
150
,
0
)),
CallFuncN::create([&](Node* sender){
//回调动作代码
}),
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, this, _grossini, true)
这样就实现了等价于 CallFuncO 的回调动作。
三、总结
在新版的回调处理中,采用了C++11中的 std::function 、std::bind 、lambda 表达式,使得回调的处理变得形式多样,代码灵活了,而其中的lambda表达式可以极大的简化回调代码,推荐使用。
- 转自:http://www.2cto.com/kf/201401/275831.html
相关推荐
cocos2d-x 3.0 人物行走 . 包里有代码和 图片资源.
这是我重新弄的cocos2d-x-3.0的类图.之前别人兄台弄的,有些不全面,有些地方错误.我这个可以说是最新的了.每个类添加了中文的详细注解,同时也添加了中文的类名称翻译.这样对cocos2d-x-3.0的框架比较好上手. 有兴趣的...
Cocos2d-x3.0正式版 练练看 源码。有注释。
兄弟连cocos2d-x3.0 final视频教程 1.Cocos2d-x手机游戏开发C编程基础 2.Cocos2d-x手机游戏开发C++编程基础 3.Cocos2d-x3.0 final手机游戏开发核心技术 4.实例:贪吃蛇 5.实例:微信飞机大战
这是cocos2d-x 3.0 类关系图, 这个制作者是:gamecocos2dx 他做的Xmind,我导出的PNG格式,我推荐还是看Xmind,里面还有一些注释 gamecocos2dx Xmind下载地址:...
这是一个cocos2d-x 3.0中文开发文档.
cocos2d-x 3.0 骨骼动画 demo 以及注意事项
http://blog.csdn.net/zoyzn/article/details/27251633一文的源码。cocos2d-x 3.0导出自定义类到lua,并导出自定义类的名称空间到lua。
cocos2d-x 3.0 rapidjson 读取Json
自制的cocos2d-x 3.0alpha1项目创建包,适用于cocos2d-x 3.0alpha1版,用此资源包创建的cocos2d-x 3.0alpha1项目,可以拷贝至任意目录下
本游戏基于cocos2d-x 3.0版本,可能不适用于cocos2d-x 2.x版本,请看清楚,再参考! 使用方法:将Classes中的类全部拷贝到新建cocos项目的Classes项目中,将Resources下的所有文件拷贝到对应的文件下,运行即可!
资源名称:Cocos2d-x实战:JS卷——Cocos2d-JS开发内容简介:本书是介绍Cocos2d-x游戏编程和开发技术书籍,介绍了使用Cocos2d-JS中核心类、瓦片地图、物理引擎、音乐音效、数据持久化、网络通信、性能优化、多平台...
官网中文docs文档的例子下载 创建工程的时候一定要创建一样的文件名 http://www.cocos2d-x.org/docs/tutorial/framework/native/how-to-drag-and-drop-sprites/zh
Cocos2d-x3.0final 自学教程的配套代码http://blog.csdn.net/column/details/cocos2dx2014.html
Cocos2d-x-3.x游戏开发之旅-钟迪龙著 全新pdf版和附书代码(代码为工程文件,可复制) 附带目录标签
Cocos2d-x3.0游戏实例《别救我》源码。 教程地址:http://blog.csdn.net/musicvs/article/details/24928929
cocos2d-x 3.0 开发文档英文版(html)
Cocos2d-x 3.0 过渡学习 尊重原创,转载来自:star特530的CSDN博客 :http://blog.csdn.net/star530?viewmode=contents
Cocos2d-x 3.0 开发(九)使用Physicals代替Box2D和chipmunk的3.0 alpha1新版本 对应于Coco2d-x 3.0 alpha1 使用,更新之前3.0 alpha0 的 文件。相关博客地址:...
cocos2d-x 3.0 离线文档 html版