在cocos2dx 3.0 版本中,回調函數基本上由4個CC_CALLBACK_N 函數代替,N代表回調函數的參數個數
1.先讓我們來看看這些CC_CALLBACK_N怎麼用
比如action的回調 ,CC_CALLBACK_0
- auto animation = Animation::create();
- auto animate = Animate::create(animation);
- CallFunc* animateDone = CallFunc::create(CC_CALLBACK_0(PlaneLayer::removePlane,this));
- auto sequence = Sequence::create(animate,animateDone,NULL);
- sprite1->runAction(sequence);
- void PlaneLayer::removePlane(){
- //.....
- }
- auto actionMove = MoveTo::create(randomDuration, Point(0, 0));
- auto actionDone = CallFuncN::create(CC_CALLBACK_1(EnemyLayer::enemy1MoveFinished,this));
- auto sequence = Sequence::create(actionMove,actionDone,NULL);
- sprite2->runAction(sequence);
- void EnemyLayer::enemy1MoveFinished(Node* pSender){
- Sprite* sprite2 = (Sprite*)pSender;
- }
或者按鈕的回調函數:CC_CALLBACK_1
- auto pauseNormal = Sprite::create("game_pause_nor.png");
- auto pausePressed = Sprite::create("game_pause_pressed.png");
- auto menuItem = MenuItemSprite::create(pauseNormal,pausePressed,NULL,CC_CALLBACK_1(ControlLayer::menuPauseCallback,this));
- menuItem->setPosition(Point::ZERO);
- auto menuPause = Menu::create(menuItem,NULL);
- menuPause->setPosition(Point::ZERO);
- //回調函數
- void ControlLayer::menuPauseCallback(Object* pSender)
- {
- //....
- }
或者touch函數:CC_CALLBACK_2
- //單點觸摸
- virtual bool onTouchBegan(Touch *touch, Event *unused_event);
- virtual void onTouchMoved(Touch *touch, Event *unused_event);
- virtual void onTouchEnded(Touch *touch, Event *unused_event);
- virtual void onTouchCancelled(Touch *touch, Event *unused_event);
- auto dispatcher = Director::getInstance()->getEventDispatcher();
- auto listener = EventListenerTouchOneByOne::create();
- listener->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan,this);
- listener->onTouchMoved = CC_CALLBACK_2(GameLayer::onTouchMoved,this);
- listener->onTouchEnded = CC_CALLBACK_2(GameLayer::onTouchEnded,this);
- listener->setSwallowTouches(true);//不向下傳遞觸摸
- dispatcher->addEventListenerWithSceneGraphPriority(listener,this);
2.發現了上面的CallFunc和CallFucnN了沒有,恩,先去LOL一把再接著寫。。
回來了。讓我先回口血,恩,接著寫...
一般來說:
CallFunc用於 不帶參數的,
CallFuncN 用於創建 帶一個Node節點參數的,Node*節點參數是動作的執行者
CCCallFuncND 比CallFuncN多了一個參數,可以是任意類型的參數 void *,用法看下面
- auto animation = AnimationCache::getInstance()->animationByName("Enemy1Blowup");
- auto animate = Animate::create(animation);
- CCCallFuncND* animateDone = CCCallFuncND::create(this,callfuncND_selector(EnemyLayer::removeEnemy1),(void*)enemy1);
- auto sequence = Sequence::create(animate, animateDone,NULL);
- Sprite* m_sprite = enemy1->getSprite();
- m_sprite ->runAction(sequence);
- void EnemyLayer::removeEnemy1(Node* pTarget, void* data){
- Sprite* m_sprite = (Sprite*) pTarget; //node節點為動作的執行者
- Enemy* enemy1 = (Enemy*)data; //我們傳的自定義數據enemy1
- //...
- }
- CCCallFuncND* animateDone = CCCallFuncND::create(this,callfuncND_selector(EnemyLayer::removeEnemy1),(void*)enemy1);
- //寫法1
- CCCallFuncN* animateDone = CCCallFuncN::create(CC_CALLBACK_1(EnemyLayer::removeEnemy1,this,enemy1));
- //寫法2
- CCCallFunc* animateDone = CCCallFunc::create(CC_CALLBACK_0(EnemyLayer::removeEnemy1,this,enemy1->getSprite(),enemy1));
- //寫法3,用std::bind
- CCCallFuncN* animateDone = CCCallFuncN::create(std::bind(&EnemyLayer::removeEnemy1,this,enemy1->getSprite(),enemy1));
恩,是不是有點亂,記不住沒關係,我也經常沒記住,我們來具體看一下CC_CALLBACK_N到底是神馬玩意
- // 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__)
是不是看到了std::bind、##__VA_ARGS__、std::placeholders::_1等等,這些都是神馬玩意,
先解釋一下:
std::placeholders::_1是參數佔位符,表示第一個參數,以此類推
那std::bind是神馬,不急我們先看一段代碼
- #include <iostream>
- #include <functional>
- using namespace std;
- typedef std::function<void ()> fp;
- void g_fun()
- {
- cout<<"g_fun()"<<endl;
- }
- class A
- {
- public:
- static void A_fun_static()
- {
- cout<<"A_fun_static()"<<endl;
- }
- void A_fun()
- {
- cout<<"A_fun()"<<endl;
- }
- void A_fun_int(int i)
- {
- cout<<"A_fun_int() "<<i<<endl;
- }
- void A_fun_int_double(int i,int p)
- {
- cout<<"A_fun_int_double ()"<<i<<","<<p<<endl;
- }
- //非靜態類成員,因為含有this指針,所以需要使用bind
- void init()
- {
- //綁定不帶參數的函數
- fp fp1=std::bind(&A::A_fun,this);
- fp1();
- }
- void init2()
- {
- typedef std::function<void (int)> fpi;
- //綁定帶一個參數的函數
- fpi f=std::bind(&A::A_fun_int,this,std::placeholders::_1);//參數要使用佔位符 std::placeholders::_1表示第一個參數
- f(5);
- }
- void init3(){
- typedef std::function<void (int,double)> fpid;
- //綁定帶兩個參數的函數
- fpid f=std::bind(&A::A_fun_int_double,this,std::placeholders::_1,std::placeholders::_2);
- f(5,10);
- }
- };
- int main()
- {
- //綁定到全局函數
- fp f2=fp(&g_fun);
- f2();
- //綁定到類靜態成員函數
- fp f1=fp(&A::A_fun_static);
- f1();
- A().init();
- A().init2();
- A().init3();
- return 0;
- }
然後看一下輸出結果:
- g_fun()
- A_fun_static()
- A_fun()
- A_fun_int() 5
- A_fun_int_double ()5,10
再解釋一下:
std::function --> 綁定到全局函數/類靜態成員函數(類靜態成員函數與全局函數沒有區別)
std::bind --> 綁定到類的非靜態成員函數
std::bind --> 綁定到類的非靜態成員函數
到這裡是不是有豁然開朗的感覺呢,哈哈,知道了bind函數怎麼用,然後我們就可以使用std::bind替換CC_CALLBACK_N寫法了
3.使用std:bind函數替換CC_CALLBACK_N:
比如我們要替換CC_CALLBACK_0
- auto animation = Animation::create();
- auto animate = Animate::create(animation);
- //CallFunc* animateDone = CallFunc::create(CC_CALLBACK_0(PlaneLayer::removePlane,this));
- CallFunc* animateDone = CallFunc::create(std::bind(&PlaneLayer::removePlane,this));//替換
- auto sequence = Sequence::create(animate,animateDone,NULL);
- sprite1->runAction(sequence);
- void PlaneLayer::removePlane(){
- //.....
- }
比如我們要替換帶一個參數的CC_CALLBACK_1
- auto actionMove = MoveTo::create(randomDuration, Point(0, 0));
- //auto actionDone = CallFuncN::create(CC_CALLBACK_1(EnemyLayer::enemy1MoveFinished,this));
- auto actionDone = CallFuncN::create(std::bind(&EnemyLayer::enemy1MoveFinished,this,enemy1));//替換
- auto sequence = Sequence::create(actionMove,actionDone,NULL);
- sprite2->runAction(sequence);
- void EnemyLayer::enemy1MoveFinished(Node* pSender){
- Sprite* sprite2 = (Sprite*)pSender;
- }
- auto animation = AnimationCache::getInstance()->animationByName("Enemy1Blowup");
- auto animate = Animate::create(animation);
- //CCCallFuncND* animateDone = CCCallFuncND::create(this,callfuncND_selector(EnemyLayer::removeEnemy1),(void*)enemy1);
- CCCallFuncN* animateDone = CCCallFuncN::create(std::bind(&EnemyLayer::removeEnemy1,this,enemy1->getSprite(),enemy1));//替換
- auto sequence = Sequence::create(animate, animateDone,NULL);
- Sprite* m_sprite = enemy1->getSprite();
- m_sprite ->runAction(sequence);
- void EnemyLayer::removeEnemy1(Node* pTarget, void* data){
- Sprite* m_sprite = (Sprite*) pTarget; //node節點為動作的執行者
- Enemy* enemy1 = (Enemy*)data; //我們傳的自定義數據enemy1
- //...
- }
哈哈,這下子很清楚了吧。。再也不會混亂了。。