zoukankan      html  css  js  c++  java
  • cocos2dx 3.0 它 使用std::bind更换CC_CALLBACK_N

    在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(){
    	//.....
    }


    或者action带一个參数的回调:CC_CALLBACK_1,在这里,pSender就是动作的运行者sprite2


    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;
    }


    或者button的回调函数: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_0 啊CC_CALLBACK_1 啊。都能够类似这么写,非常多种写法。原因是由于CC_CALLBACK_N有一个可变參数宏##__VA_ARGS__



    恩。是不是有点乱。记不住没关系,我也常常没记住,我们来详细看一下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等等。这些都是神马玩意,


    先解释一下:


    ##__VA_ARGS__是可变參数宏
    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       --> 绑定到类的非静态成员函数


    到这里是不是有豁然开朗的感觉呢。哈哈,知道了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
    	//...
    }


    哈哈,这下子非常清楚了吧。。再也不会混乱了。。




    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    URAL 1998 The old Padawan 二分
    URAL 1997 Those are not the droids you're looking for 二分图最大匹配
    URAL 1995 Illegal spices 贪心构造
    URAL 1993 This cheeseburger you don't need 模拟题
    URAL 1992 CVS
    URAL 1991 The battle near the swamp 水题
    Codeforces Beta Round #92 (Div. 1 Only) A. Prime Permutation 暴力
    Codeforces Beta Round #7 D. Palindrome Degree hash
    Codeforces Beta Round #7 C. Line Exgcd
    Codeforces Beta Round #7 B. Memory Manager 模拟题
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4662172.html
Copyright © 2011-2022 走看看