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:

class CC_DLL Action :public Ref,public Clonable

{

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);//继续




你可能感兴趣的:(技术,Cocos2dx,c++)