近日,由於自己需要用到一個特效道具,show完特效後會刪除場上幾個同一類的精靈,爲避免同時使用這兩個道具時,產生衝突,導致前一個特效的精靈未被刪除,所以想了個自定義回調函數的方法,衆所周知,定義一個回調函數的用法大致是:
__String* draw = __String::create("1");
draw->retain();
for (auto sprite : _sp)
{
i++;
auto time=DelayTime::create(0.002f * i);
auto call = __CCCallFuncND::create(this,callfuncND_selector(gameLayer::showLine),draw);//callfuncND_selector算是一個比較常見的,傳遞一個void類型的參數
sprite->setTag((int)_sp.size());
sprite->runAction(Sequence::create(time,call, NULL));
}
但是翻遍底層邏輯,回調函數裏邊並不支持別的類型,轉到callfuncND_selector的定義處,我們可以清楚的看到:
class Node;
typedef void (Ref::*SEL_CallFunc)();
typedef void (Ref::*SEL_CallFuncN)(Node*);
typedef void (Ref::*SEL_CallFuncND)(Node*, void*);
typedef void (Ref::*SEL_CallFuncO)(Ref*);
typedef void (Ref::*SEL_MenuHandler)(Ref*);
typedef void (Ref::*SEL_SCHEDULE)(float);
#define callfunc_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFunc>(&_SELECTOR)
#define callfuncN_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncN>(&_SELECTOR)
#define callfuncND_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncND>(&_SELECTOR)
#define callfuncO_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncO>(&_SELECTOR)
#define menu_selector(_SELECTOR) static_cast<cocos2d::SEL_MenuHandler>(&_SELECTOR)
#define schedule_selector(_SELECTOR) static_cast<cocos2d::SEL_SCHEDULE>(&_SELECTOR)
其中只支持void,node,ref以及float等類型,而我現在需要一個能夠傳遞Vector的回調函數,所以只有自己重寫一個了,因爲正好callfuncND_selector滿足我需要的格式,傳遞一個psender,以及一個void類型的函數,所以可以抄襲這個類:
class CC_DLL __CCCallFuncND : public CallFunc
{
public:
/** creates the action with the callback and the data to pass as an argument */
CC_DEPRECATED_ATTRIBUTE static __CCCallFuncND * create(Ref* target, SEL_CallFuncND selector, void* d);
//
// Overrides
//
virtual __CCCallFuncND* clone() const override;
virtual void execute() override;
protected:
__CCCallFuncND() {}
virtual ~__CCCallFuncND() {}
/** initializes the action with the callback and the data to pass as an argument */
bool initWithTarget(Ref* target, SEL_CallFuncND selector, void* d);
SEL_CallFuncND _callFuncND;
void* _data;
private:
CC_DISALLOW_COPY_AND_ASSIGN(__CCCallFuncND);
};
將自己需要的回調函數重寫:
//重寫動作回調函數
typedef void (Ref::*ZYFun)(Node*, Vector<Mysprite*>);//將ZYFun聲明爲帶node,和一個容器的函數,其中Mysprite是我自定義的類,繼承自Sprite
#define zy_selector(_SELECTOR) static_cast<::ZYFun>(&_SELECTOR)//再宏定義zy_selector回調形式
class CC_DLL __ZYCallFuncND : public CallFunc //重寫回調函數的類,取名叫__ZYcallFuncND類似<span style="font-family: Menlo;">__CCCallFuncND</span>
{
public:
// CC_DEPRECATED_ATTRIBUTE
static __ZYCallFuncND * create(Ref* target, ZYFun selector, Vector<Mysprite*> d);//將參數換成自己的,傳遞的內容換成自定義的容器形式
virtual __ZYCallFuncND* clone() const override;
virtual void execute() override;
protected:
__ZYCallFuncND() {}
virtual ~__ZYCallFuncND() {}
/** initializes the action with the callback and the data to pass as an argument */
bool initWithTarget(Ref* target, ZYFun selector,Vector<Mysprite*> d);
ZYFun _callFuncND;
Vector<Mysprite*> _data;
private:
CC_DISALLOW_COPY_AND_ASSIGN(__ZYCallFuncND);
};
再看下cpp文件:
//__ZYCallFuncND自定義的回調函數
__ZYCallFuncND * __ZYCallFuncND::create(Ref* target, ZYFun selector, Vector<Mysprite*> d)
{
__ZYCallFuncND* ret = new __ZYCallFuncND();
if (ret && ret->initWithTarget(target, selector, d))
{
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
bool __ZYCallFuncND::initWithTarget(Ref* target, ZYFun selector, Vector<Mysprite*> d)
{
if (CallFunc::initWithTarget(target))
{
_data = d;
_callFuncND = selector;
return true;
}
return false;
}
void __ZYCallFuncND::execute()
{
if (_callFuncND)
{
(_selectorTarget->*_callFuncND)(_target, _data);
}
}
__ZYCallFuncND * __ZYCallFuncND::clone() const
{
// no copy constructor
auto a = new __ZYCallFuncND();
if( _selectorTarget)
{
a->initWithTarget(_selectorTarget, _callFuncND, _data);
}
a->autorelease();
return a;
}
最後你就可以使用自己的回調函數形式,順利的傳入自己的容器了:
if (_spp.size()>0)
{
auto call = __ZYCallFuncND::create(this,zy_selector(gameLayer::boomefover),_spp);
auto timee=DelayTime::create(0.3);
this->runAction(Sequence::create(timee,call, NULL));
}