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


    或者按钮的回调函数: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
    	//...
    }


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




  • 相关阅读:
    openerp学习笔记 调用工作流
    openerp学习笔记 自定义小数精度(小数位数)
    openerp学习笔记 跟踪状态,记录日志,发送消息
    openerp学习笔记 计算字段、关联字段(7.0中非计算字段、关联字段只读时无法修改保存的问题暂未解决)
    openerp学习笔记 tree视图增加复选处理按钮
    openerp学习笔记 统计、分析、报表(过滤条件向导、分组报表、图形分析、比率计算、追加视图排序)
    openerp学习笔记 视图样式(表格行颜色、按钮,字段只读、隐藏,按钮状态、类型、图标、权限,group边距,聚合[合计、平均],样式)
    openerp学习笔记 计划动作、计划执行(维护计划)
    银行前置以及银行核心系统
    什么是报文
  • 原文地址:https://www.cnblogs.com/fzll/p/3954604.html
Copyright © 2011-2022 走看看