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
	//...
}


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




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

你可能感兴趣的:(cocos2dx)