Cocos2d-x 3.x基础学习: 回调函数std::bind总结
自从Cocos2d-x 3.0引入了C++11标准后,回调函数采用了新的函数适配器:std::function和std::bind。曾经的回调函数menu_selector、callfunc_selector、cccontrol_selector等已被弃用,取而代之的是一系列的CC_CALLBACK_*。
1. std::bind相关宏定义
Cocos2d-x总共使用了4个std::bind的宏定义,其核心在于使用std::bind进行函数适配。
std::placeholders::_1:不定参数,不事先指定,而是在调用的时候传入。##__VA_ARGS__:可变参数列表。
以下是具体的宏定义:
// 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_CALLBACK_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__)
2. 变更的回调函数
2.1 动作函数
动作函数相关的回调包括CallFunc、CallFuncN等。可以直接使用CC_CALLBACK_0、CC_CALLBACK_1,也可以直接使用std::bind。
CallFunc:使用CC_CALLBACK_0,不带任何不定参数。CallFuncN:使用CC_CALLBACK_1,需要默认传入不定参数placeholders::_1,其值为调用该动作的对象(如sprite->runAction(callfun),那么默认的一个不定参数_1为sprite)。
2.x版本示例
// 2.x版本
CallFunc::create (this, callfunc_selector (HelloWorld::callback0) );
CCCallFuncN::create (this, callfuncN_selector (HelloWorld::callback1) );
CCCallFuncND::create(this, callfuncND_selector(HelloWorld::callback2), (void *)10 );
// 回调函数
void HelloWorld::callback0() { } // CCCallFunc回调函数
void HelloWorld::callback1(CCNode* node) { } // CCCallFuncN回调函数
void HelloWorld::callback2(CCNode* node,void* a) { } // CCCallFuncND回调函数,参数必须为void*
3.x版本示例
// 3.x版本
// 使用 CC_CALLBACK_*
CallFunc::create ( CC_CALLBACK_0(HelloWorld::callback0, this) );
CallFuncN::create( CC_CALLBACK_1(HelloWorld::callback1, this) );
CallFuncN::create( CC_CALLBACK_1(HelloWorld::callback2, this, 0.5));
// 使用 std::bind
// 其中sprite为执行动作的精灵
CallFunc::create (std::bind(&HelloWorld::callback0, this ) );
CallFuncN::create(std::bind(&HelloWorld::callback1, this, sprite));
CallFuncN::create(std::bind(&HelloWorld::callback2, this, sprite, 0.5));
// 回调函数
void HelloWorld::callback0() { }
void HelloWorld::callback1(Node* node) { }
void HelloWorld::callback2(Node* node, float a) { } // 可自定义参数类型float
如果你对std::bind很熟悉,对于CallFunc、CallFuncN回调函数的绑定,也可以全部使用std::bind,示例如下:
// callback0
CallFunc::create(std::bind(&HelloWorld::callback0, this));
// callback1
CallFunc::create (std::bind(&HelloWorld::callback1, this, sprite));
CallFuncN::create(std::bind(&HelloWorld::callback1, this, std::placeholders::_1));
// callback2
CallFunc::create (std::bind(&HelloWorld::callback2, this, sprite, 0.5));
CallFuncN::create(std::bind(&HelloWorld::callback2, this, std::placeholders::_1, 0.5));
// 回调函数
void HelloWorld::callback0() { }
void HelloWorld::callback1(Node* node) { }
void HelloWorld::callback2(Node* node, float a) { } // 可自定义参数类型float
2.2 菜单项回调menu_selector
可以使用CC_CALLBACK_1,也可以直接使用std::bind。
2.x版本示例
// 2.x版本
MenuItemImage::create("1.png", "2.png", this, menu_selector(HelloWorld::callback));
3.x版本示例
// 3.x版本
// CC_CALLBACK_1
MenuItemImage::create("1.png", "2.png", CC_CALLBACK_1(HelloWorld::callback1, this));
// std::bind
MenuItemImage::create("1.png", "2.png", std::bind(&HelloWorld::callback1, this, std::placeholders::_1));
// 回调函数
void HelloWorld::callback(Node* sender) { }
2.3 触控事件回调
使用CC_CALLBACK_2。
// 创建一个事件监听器类型为 单点触摸
auto touchLisner = EventListenerTouchOneByOne::create();
// 绑定事件
touchLisner->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
touchLisner->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
touchLisner->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
// 回调函数
virtual bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event);
virtual void HelloWorld::onTouchMoved(Touch *touch, Event *unused_event);
virtual void HelloWorld::onTouchEnded(Touch *touch, Event *unused_event);
3. 未变更的回调函数
3.1 定时器回调schedule_selector
依旧使用schedule_selector。
// 定时器
schedule(schedule_selector(HelloWorld::update), 1.0/60.0);
// 回调函数
void HelloWorld::update(float dt) { }
3.2 按钮事件回调cccontrol_selector
依旧使用cccontrol_selector。
// 按钮事件绑定
button->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::callback), Control::EventType::TOUCH_DOWN);
// 回调函数
void HelloWorld::callback(Node* sender, Control::EventType controlEvent) { }
4. 扩展回调函数
在3.x版本中,事件的回调函数可以带任意个自定义的参数。以下以菜单项回调函数为例:
auto sprite = Sprite::create("CloseNormal.png");
sprite->setPosition(Vec2(visibleSize / 2) );
this->addChild(sprite);
auto itemImage = MenuItemImage::create(
"CloseNormal.png",
"CloseNormal.png",
std::bind(&HelloWorld::callback4, this, std::placeholders::_1, sprite, 10, 0.5));
itemImage->setPosition(Vec2(visibleSize / 4));
auto pMenu = Menu::create(itemImage, NULL);
pMenu->setPosition(Vec2::ZERO);
this->addChild(pMenu);
// 回调函数
void HelloWorld::callback4(Node* sender, Sprite* bg, int a, float b)
{
bg->setScale(a * b);
}
通过以上内容,我们可以清晰地了解Cocos2d-x 3.x中回调函数std::bind的使用方法和相关变更情况。在实际开发中,根据不同的需求选择合适的回调方式,能够更高效地完成开发任务。