cocos2dx[3.2](8)——新回撥函式std::bind
阿新 • • 發佈:2019-02-07
【嘮叨】
自從3.0引用了C++11標準後,回撥函式採用的新的函式介面卡:std::function、std::bind。
而曾經的回撥函式menu_selector、callfunc_selector、cccontrol_selector等都已經被無情的拋棄了。
取而代之的則是一系列的CC_CALLBACK_*。
【std::bind】
0、std::bind
請參照上面兩篇文章。
1、CC_CALLBACK_*
cocos2dx總共使用了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、變更的回撥函式
> 動作函式 :CallFunc/CallFuncN callfunc_selector / callfuncN_selector / callfuncND_selector > 選單項回撥:menu_selector > 觸控事件 :onTouchBegan / onTouchMoved / onTouchEnded
2.1、動作函式CallFunc
可以直接使用CC_CALLBACK_0、CC_CALLBACK_1,也可以直接使用std::bind。
> CallFunc :使用CC_CALLBACK_0。不帶任何不定引數。
> CallFuncN:使用CC_CALLBACK_1。需要預設傳入不定引數 placeholders::_1,其值為:呼叫該動作的物件(如sprite->runAction(callfun),那麼預設的一個不定引數 _1 為 sprite)。
/**
* 函式動作
* - CallFunc
* - CallFuncN
* - CallFuncND與CallFuncO已被遺棄,請使用CallFuncN替代
*/
//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版本
//使用 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版本
MenuItemImage::create("1.png", "2.png", this, menu_selector(HelloWorld::callback));
//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版本中,事件的回撥函式可以帶任意個自定義的引數啦。
舉個栗子:(以選單項回撥函式為例)
請看回調函式callback4。
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);
}