cocos2dx action test

1、CCToggleVisibility对当前的action动作的精灵对象进行取反的visible设置

    CCActionInterval*  move1 = CCMoveBy::create(1, ccp(250,0));
    CCActionInterval*  move2 = CCMoveBy::create(1, ccp(0,50));
    CCToggleVisibility*  tog1 = new CCToggleVisibility();
    CCToggleVisibility*  tog2 = new CCToggleVisibility();
    tog1->autorelease();
    tog2->autorelease();
    CCFiniteTimeAction*  seq = CCSequence::create( move1, tog1, move2, tog2, move1->reverse(), NULL);
    m_kathia->runAction(seq);

如上显示的动作将会是move1执行1秒然后tog1隐藏,因为当前是隐藏状态所以move2的动作将会处于隐藏状态的执行,当执行到tog2的时候将move2之后的位置显示出来因为之前是隐藏状态所以现在转成显示的,然后再执行move1->reverse()

具体CCToggleVisibility的执行原理可以看他源代码的update函数

void CCToggleVisibility::update(float time) 
{
    m_pTarget->setVisible(!m_pTarget->isVisible());
}

当action执行到CCToggleVisibility的时候,只做一个动作就是取反设置该执行精灵的visible

 

2、removeFromParentAndCleanup 从父节点移除自己,后面的bCleanUp是判断是否移除action

当调用该函数的时候,不管bCleanUp是true还是false都会从父节点中移除自己(引用计数减1);当bCleanUp为true的时候则删除之前回去调用自身拥有的action的release;如果没有调用true会产生本身移除了,但是action对象没有被删除的情况。

这种情况只有用在你想保留该节点的action留作他用。使用时候需要很注意。具体调用的源码如下所示

复制代码
void CCNode::detachChild(CCNode *child, bool doCleanup)
{
    // IMPORTANT:
    //  -1st do onExit
    //  -2nd cleanup
    if (m_bRunning)
    {
        child->onExitTransitionDidStart();
        child->onExit();
    }
    // If you don't do cleanup, the child's actions will not get removed and the
    // its scheduledSelectors_ dict will not get released!
    if (doCleanup)
    {
        child->cleanup();
    }
    // set parent nil at the end
    child->setParent(NULL);
    m_pChildren->removeObject(child);
}
复制代码

如上先判断是否是在running;因为调用一个节点的显示的时候,调用顺序是这样子的:

m_pRunningScene->onEnter();
m_pRunningScene->onEnterTransitionDidFinish();

所以当要停止调用的时候需要反过来停止。

然后判断是否cleanup再移除本身的节点。

如果只是想从父节点移除,放置到另一个父节点则不能调用removeFromParentAndCleanup;需要使用

m_grossini->retain();
m_grossini->removeFromParentAndCleanup(false);

3、CCCallFuncN继承action,对应的回调函数有一个node参数

构造的时候类似于这样子:CCCallFuncN::create( this, callfuncN_selector(ActionRepeatForever::repeatForever) ),即this中有一个repeatForever的函数当调用该action的时候会去调用该函数,并传入谁执行这个action的哪个node

void ActionRepeatForever::repeatForever(CCNode* pSender)
{
    CCRepeatForever *repeat = CCRepeatForever::create( CCRotateBy::create(1.0f, 360) );

    pSender->runAction(repeat);
}

如上,则可以在psender添加对应的action;

执行顺序:m_grossini->runAction(action); 会调用CCCallFunc的update函数,然后update会调用this->execute();因为execute是虚函数,在CCCallFuncN中有对应的实现,所以会调用CCCallFuncN的execute函数,如下所示

void CCCallFuncN::execute() {
    if (m_pCallFuncN) {
        (m_pSelectorTarget->*m_pCallFuncN)(m_pTarget);
    }
。。。
}

m_pTarget就是调用执行该actionfunc的对象。

 

4、Spawn: Jump + Rotate

关于这个比较有意思的是页面的动画显示的很和谐:共跳四下,刚好也转720度。

    CCAction*  action = CCSpawn::create(
        CCJumpBy::create(2, ccp(300,0), 50, 4),
        CCRotateBy::create( 2,  720),
        NULL);

可以在设置动作叠加的时候使用ccspawn;spawn每次都是将两个动作一起叠加;当有多个动作要叠加的时候

    unsigned  int count = arrayOfActions->count();
    CCFiniteTimeAction* prev = (CCFiniteTimeAction*)arrayOfActions->objectAtIndex(0);
    for (unsigned int i = 1; i < arrayOfActions->count(); ++i)
        prev = createWithTwoActions(prev, (CCFiniteTimeAction*)arrayOfActions->objectAtIndex(i));
return (CCSpawn*)prev;
CCSpawn* CCSpawn::createWithTwoActions(CCFiniteTimeAction *pAction1, CCFiniteTimeAction *pAction2)
{
    CCSpawn *pSpawn = new CCSpawn();
    pSpawn->initWithTwoActions(pAction1, pAction2);
    pSpawn->autorelease();

    return pSpawn;
}

如上所示,每次将两个动作组合成一个spawn,然后再跟下一个动作再叠加。然后在显示的时候

void CCSpawn::update(float time){
    if (m_pOne)
        m_pOne->update(time);
    if (m_pTwo)
        m_pTwo->update(time);
}

会调用每个动作的update,子spawn的update又会调用子spawn的update。所以这里每一个时刻都会通过递归调用当前这一时刻的所有动作。

如果两个动作的时间不一样,在initWithTwoActions会进行CCDelayTime时间差的处理。使得两个动作最后使用的时间是一样的。

 

6、CCScaleTo 图片长宽比的减小或者增大到指定的比例

create(float duration, float sx, float sy);第一个参数是动作的时间,第二个和第三个参数是缩小或者放大的比例,如果小于1则是缩小,大于1则是放大。

可以使用scaleto来实现翻牌的动作。如下所示

复制代码
    rv->setVisible(false);
    CCScaleTo* small_ = CCScaleTo::create(1, 0, 1); // 设置动作时间为1秒,x轴最终变成0,y轴的比例不变
    CCScaleTo* back_ = CCScaleTo::create(1, 1, 1); // 设置动作的时间为1秒,x轴跟y轴的比例变成1即还原到原来的大小

    CCSequence* old_ = CCSequence::create(small_, CCRemoveSelf::create(), NULL);// 变小动作结束之后将自己删除,该动作调用的是removeFromParentAndCleanup
    CCSequence* new_ = CCSequence::create(CCScaleTo::create(0, 0, 1), CCShow::create(), back_, NULL); // 将自己的x轴变为0,然后显示出来,再然后慢慢还原

    CCTargetedAction* a_ = CCTargetedAction::create(m_grossini, old_);
    rv->runAction(CCSequence::create(a_, new_, NULL));
复制代码

先将最终显示的设置精灵rv为不可见。

posted @   LCAC  阅读(166)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示