1. 程式人生 > >cocos2dx暫停某個action動作並恢復&簡單的js-binding

cocos2dx暫停某個action動作並恢復&簡單的js-binding

最近有個需求是一個卡牌同時執行兩個動作,一個repearForever的跳著向前移動,還有一個卡牌翻轉的動作。

有個需求是使用道具讓卡牌停止跳著移動,而卡牌可以翻轉。持續5s後,卡牌繼續跳著向前。

試了一些方法,也百度了一些方法,並看了原始碼,沒找到合適的引擎自帶方法。

有說stopActionBrTag(TAG);然後重新runAction()該動作的,但實際並不是想要的效果,比如牌剛好跳在最高點時,再次runAction()的時候,會從最高點開始運動。

如果紀錄position的話,會瞬移,而且有其他動作也在改變positoin的話,控制起來會很困難。

於是改了下原始碼。只看前兩步即可。其中步驟4之後是由於我用的CocosCreator,需要用js程式碼掉用c++的程式碼。

----1.CCAction.h(2d/actions/CCAction.h)新增變數&get/set:

classCC_DLL Action :publicRef,publicClonable

{

public:

    /** 控制動作暫停並繼續的標誌位 evanFlag */

    bool evanFlag;

    inline int getEvanFlag()const { returnevanFlag; }

    inline void setEvanFlag(bool _evanFlag) {evanFlag = _evanFlag; }

/** Default tag used for all the actions. */

    static constint INVALID_TAG = -1;

    /**

     * @js NA

     * @lua NA

     */

    virtual std::string description()const;

----2.CCActionManager.cpp(2d/actions/CCActionManager.cpp)類中

         voidActionManager::update(float dt)方法新增程式碼:

if (_currentTarget->currentAction->evanFlag) {

     continue

;

}

新增後代碼:

// main loop

void ActionManager::update(float dt)

{

    for (tHashElement *elt =_targets; elt != nullptr; )

    {

        _currentTarget = elt;

_currentTargetSalvaged =false;

if (!_currentTarget->paused)

        {

// The 'actions' MutableArray may change while inside this loop.

for (_currentTarget->actionIndex =0; _currentTarget->actionIndex <_currentTarget->actions->num;

_currentTarget->actionIndex++)

            {

_currentTarget->currentAction = (Action*)_currentTarget->actions->arr[_currentTarget->actionIndex];

if (_currentTarget->currentAction ==nullptr)

                {

                    continue;

                }

_currentTarget->currentActionSalvaged =false;

                //evanFlag

if (_currentTarget->currentAction->evanFlag) {

                    continue;

                }

_currentTarget->currentAction->step(dt);

if (_currentTarget->currentActionSalvaged)

                {

// The currentAction told the node to remove it. To prevent the action from

// accidentally deallocating itself before finishing its step, we retained

// it. Now that step is done, it's safe to release it.

                    _currentTarget->currentAction->release();

                } else

if (_currentTarget->currentAction->isDone())

                {

                    _currentTarget->currentAction->stop();

                    Action *action = _currentTarget->currentAction;

// Make currentAction nil to prevent removeAction from salvaging it.

_currentTarget->currentAction =nullptr;

                    removeAction(action);

                }

_currentTarget->currentAction =nullptr;

            }

        }

// elt, at this moment, is still valid

// so it is safe to ask this here (issue #490)

        elt = (tHashElement*)(elt->hh.next);

// only delete currentTarget if no actions were scheduled during the cycle (issue #481)

if (_currentTargetSalvaged &&_currentTarget->actions->num ==0)

        {

deleteHashElement(_currentTarget);

        }

////if some node refrence 'target', it's refrence count >= 2 (issues #14050)

        else if(_currentTarget->target->getReferenceCount() ==1)

        {

deleteHashElement(_currentTarget);

        }

    }

// issue #635

_currentTarget =nullptr;

}

----3.使用:

sprite =Sprite::create("new/btn/btn_2_cheng_n.png");

    this->addChild(sprite);

    sprite->setPosition(Vec2(200,200));

    auto moveBy = MoveBy::create(2,Vec2(20, 20));

    auto moveBack = moveBy->reverse();

    auto sequence = Sequence::create(moveBy, moveBack, NULL);

    auto repeat = RepeatForever::create(sequence);

    repeat->setTag(9);

    auto scaleBy = ScaleBy::create(2,1.1);

    auto scaleBack = scaleBy->reverse();

    auto sequence1 = Sequence::create(scaleBy, scaleBack, NULL);

    auto repeat1 = RepeatForever::create(sequence1);

    sprite->runAction(repeat);

    sprite->runAction(repeat1);

    sprite->getActionByTag(9)->evanFlag = true;//暫停

    sprite->getActionByTag(9)->evanFlag = false;//繼續

-----------------js-binding------------------

----4.jsb_cocos2dx_auto.cpp(auto/jsb_cocos2dx_auto.cpp)中新增方法

我加在了js_cocos2dx_Action_setTag()方法之後,大概12575行。

//evanFlag

bool js_cocos2dx_Action_setEvanFlag(JSContext *cx,uint32_t argc, jsval *vp)

{

    JS::CallArgs args =JS::CallArgsFromVp(argc, vp);

    bool ok = true;

    JS::RootedObject obj(cx, args.thisv().toObjectOrNull());

    js_proxy_t *proxy = jsb_get_js_proxy(obj);

    cocos2d::Action* cobj = (cocos2d::Action *)(proxy ? proxy->ptr :NULL);

JSB_PRECONDITION2( cobj, cx,false, "js_cocos2dx_Action_setEvanFlag : Invalid Native Object");

    if (argc == 1) {

        bool arg0;

        arg0 = JS::ToBoolean(args.get(0));

JSB_PRECONDITION2(ok, cx,false, "js_cocos2dx_Action_setEvanFlag : Error processing arguments");

        cobj->setEvanFlag(arg0);

        args.rval().setUndefined();

        return true;

    }

JS_ReportError(cx,"js_cocos2dx_Action_setEvanFlag : wrong number of arguments: %d, was expecting %d", argc,1);

return false;

}

----5.jsb_cocos2dx_auto.cpp(auto/jsb_cocos2dx_auto.cpp)中

js_register_cocos2dx_Action()方法新增程式碼:

同樣,我加在了setTag之後,新增完上述方法後大概12738行。

JS_FN("setEvanFlag",js_cocos2dx_Action_setEvanFlag,1, JSPROP_PERMANENT |JSPROP_ENUMERATE),

----6.js程式碼中掉用:

var action = cc.director.getActionManager().getActionByTag(9, this.node);
action.setEvanFlag(true);//暫停

action.setEvanFlag(false);//繼續