cocos2dx3.0自定義回調函數,傳遞自己想要的參數

         近日,由於自己需要用到一個特效道具,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));
    }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章