乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      【玩轉(zhuǎn)cocos2d-x之二十七】CCSequence不能執(zhí)行CCRepeatForever

       Kitsdk 2014-02-24

      原創(chuàng)作品,轉(zhuǎn)載請(qǐng)標(biāo)明http://blog.csdn.net/jackystudio/article/details/17019023


      之前在遇到這么一個(gè)問題,在CCSequence中加入CCRepeatForever,發(fā)現(xiàn)其他動(dòng)作執(zhí)行沒問題,就是CCRepeatForever無法執(zhí)行。代碼并沒有問題,很奇怪。


      1.示例

      1. CCBlink* blink=CCBlink::create(0.5f,10);//創(chuàng)建閃爍動(dòng)畫,duration=0.5s  
      2. CCAnimation* animation=CCAnimation::create();  
      3. animation->addSpriteFrameWithFileName("CloseNormal.png");  
      4. animation->addSpriteFrameWithFileName("CloseSelected.png");  
      5. animation->setDelayPerUnit(1.0f);//幀間間隔1s  
      6. CCAnimate* animate=CCAnimate::create(animation);//創(chuàng)建幀動(dòng)畫  
      7. CCRepeatForever* repeat=CCRepeatForever::create(animate);  
      8. CCSequence* sequence=CCSequence::create(blink,repeat,NULL);//創(chuàng)建連續(xù)動(dòng)畫  
      9. CCSprite* close=CCSprite::create("CloseNormal.png");  
      10. close->setPosition(ccp(240,160));  
      11. this->addChild(close);  
      12. close->runAction(sequence);//執(zhí)行連續(xù)動(dòng)畫  
      結(jié)果精靈閃爍10次以后,幀動(dòng)畫不執(zhí)行了。


      2.原因

      先了解一下CCSequence的創(chuàng)建和執(zhí)行原理


      2.1.CCSequence的創(chuàng)建

      創(chuàng)建CCSequence調(diào)用

      1. //創(chuàng)建CCSequence  
      2. CCSequence* CCSequence::create(CCFiniteTimeAction *pAction1, ...)  
      內(nèi)部調(diào)用了createWithVariableList,從實(shí)現(xiàn)可以看出這是一個(gè)遞歸調(diào)用。

      1. //獲取動(dòng)作列表,創(chuàng)建CCSequence  
      2. CCSequence* CCSequence::createWithVariableList(CCFiniteTimeAction *pAction1, va_list args)  
      3. {  
      4.     CCFiniteTimeAction *pNow;//當(dāng)前動(dòng)作  
      5.     CCFiniteTimeAction *pPrev = pAction1;//第一個(gè)動(dòng)作  
      6.     bool bOneAction = true;//只有一個(gè)動(dòng)作的標(biāo)志位  
      7.   
      8.     while (pAction1)  
      9.     {  
      10.         pNow = va_arg(args, CCFiniteTimeAction*);//獲取當(dāng)前動(dòng)作  
      11.         if (pNow)//如果存在  
      12.         {  
      13.             pPrev = createWithTwoActions(pPrev, pNow);//用前兩個(gè)動(dòng)作創(chuàng)建CCSequence并賦給第一個(gè)動(dòng)作  
      14.             bOneAction = false;//置false  
      15.         }  
      16.         else//如果不存在  
      17.         {  
      18.             // If only one action is added to CCSequence, make up a CCSequence by adding a simplest finite time action.  
      19.             if (bOneAction)//如果只有一個(gè)動(dòng)作  
      20.             {  
      21.                 pPrev = createWithTwoActions(pPrev, ExtraAction::create());  
      22.             }  
      23.             break;//跳出循環(huán)  
      24.         }  
      25.     }  
      26.       
      27.     return ((CCSequence*)pPrev);//返回第一個(gè)動(dòng)作  
      28. }  
      假如有3個(gè)動(dòng)作要被串聯(lián),則先把第1個(gè)和第2個(gè)串聯(lián)一個(gè)CCSequence,再把這個(gè)CCSequence和第3個(gè)動(dòng)作串聯(lián)成最終的CCSequence,然后返回。從CCSequence的成員變量可以看到:

      1. CCFiniteTimeAction *m_pActions[2];//表明只包含2個(gè)動(dòng)作對(duì)象指針  
      使用遞歸多少會(huì)降低程序的運(yùn)行效率,但是卻可以換來代碼的簡(jiǎn)潔性,同樣的CCSpawn也是這么實(shí)現(xiàn)的。

      在createWithTwoActions中,調(diào)用了initWithTwoActions函數(shù),實(shí)現(xiàn)了把兩個(gè)動(dòng)作串成一個(gè)CCSequence,關(guān)鍵代碼如下:

      1. float d = pActionOne->getDuration() + pActionTwo->getDuration();//獲取兩個(gè)動(dòng)作的duration  
      2. CCActionInterval::initWithDuration(d);//賦給新的CCSequence  
      3.   
      4. m_pActions[0] = pActionOne;//同時(shí)把兩個(gè)動(dòng)作賦給m_pActions指針數(shù)組  
      5. pActionOne->retain();  
      6.   
      7. m_pActions[1] = pActionTwo;  
      8. pActionTwo->retain();  

      2.2.duration

      從示例可以看出,閃爍動(dòng)畫blink的duration是0.5s,那CCRepeatForever呢?1s?當(dāng)然不是,1s只是幀動(dòng)畫animate的幀間間隔,每個(gè)幀動(dòng)畫包含2幀,而CCRepeatForever的duration是0。因此,當(dāng)示例中的閃爍動(dòng)畫blink和重復(fù)動(dòng)畫repeat串聯(lián)成CCSequence sequence的時(shí)候,sequence的duration就變成0.5+0=0.5s,這很重要。


      2.3.m_split

      CCSequence中有這么一個(gè)成員變量

      1. float m_split;//記錄了第一個(gè)動(dòng)畫時(shí)長(zhǎng)占總時(shí)長(zhǎng)的比例,也就是2個(gè)動(dòng)畫的時(shí)長(zhǎng)分界  
      當(dāng)執(zhí)行runAction的時(shí)候,CCSequence會(huì)調(diào)用

      1. void CCSequence::startWithTarget(CCNode *pTarget)  
      2. {  
      3.     CCActionInterval::startWithTarget(pTarget);  
      4.     m_split = m_pActions[0]->getDuration() / m_fDuration;//獲取第一個(gè)動(dòng)畫占總時(shí)長(zhǎng)的比例  
      5.     m_last = -1;  
      6. }  
      而這里由于blink占了0.5s,repeat占了0s,總時(shí)長(zhǎng)0.5s,所以m_split是0.5/0.5=1。blink占滿了整個(gè)CCSequence。這時(shí)候再來看CCSequence::update(float dt)函數(shù)的執(zhí)行,就會(huì)恍然大悟了。

      1. int found = 0;//當(dāng)前播放動(dòng)作索引  
      2. float new_t = 0.0f;//新播放進(jìn)度  
      3.   
      4. if( t < m_split ) {//播放進(jìn)度<分界進(jìn)度  
      5.     found = 0;//設(shè)置當(dāng)前播放的是第一個(gè)動(dòng)作  
      6.     if( m_split != 0 )//如果第一個(gè)動(dòng)作時(shí)長(zhǎng)占比!=0  
      7.         new_t = t / m_split;//計(jì)算出第一個(gè)動(dòng)作新的播放進(jìn)度  
      8.     else  
      9.         new_t = 1;//設(shè)置第一個(gè)已播放完畢  
      10.   
      11. else {//播放進(jìn)度>=分界進(jìn)度  
      12.     found = 1;//設(shè)置當(dāng)前播放的是第二個(gè)動(dòng)作  
      13.     if ( m_split == 1 )//如果第一個(gè)動(dòng)作時(shí)長(zhǎng)占比==1  
      14.         new_t = 1;//設(shè)置第二個(gè)動(dòng)作已完成  
      15.     else  
      16.         new_t = (t-m_split) / (1 - m_split );//計(jì)算出第二個(gè)動(dòng)作新的播放進(jìn)度  
      17. }  


      3.注意

      (1)CCSpawn也會(huì)有這個(gè)問題,所以CCSpawn也無法執(zhí)行加入其中的CCRepeatForever動(dòng)作。

      (2)CCRepeatForever的反轉(zhuǎn)動(dòng)作也是無效了,一個(gè)不會(huì)停止的動(dòng)作從什么地方開始反轉(zhuǎn)?當(dāng)然你可以先把動(dòng)作反轉(zhuǎn)了再加入CCRepeatForever中,這是沒問題的。


      4.解決方案

      (1)對(duì)于同時(shí)動(dòng)作,不使用CCSpawn,采用分別執(zhí)行

      1. close->runAction(blink);  
      2. close->runAction(repeat);  
      (2)對(duì)于連續(xù)動(dòng)作,不直接往CCSequence中加入CCRepeatForever,而是把CCRepeatForever放入瞬時(shí)動(dòng)作CCCallFunc中,再把CCCallFunc加入CCSequence中執(zhí)行。

      1. close=CCSprite::create("CloseNormal.png");  
      2. CCBlink* blink=CCBlink::create(0.5f,10);  
      3. CCCallFunc* callFunc=CCCallFunc::create(this,callfunc_selector(TestScene::repeatFunc));//創(chuàng)建CCCallFunc對(duì)象  
      4. CCSequence* sequence=CCSequence::create(blink,callFunc,NULL);//把CCCallFunc對(duì)象加入CCSequence中  
      5. close->setPosition(ccp(240,160));  
      6. this->addChild(close);  
      7. close->runAction(sequence);  
      8.   
      9.   
      10. void TestScene::repeatFunc()  
      11. {  
      12.     CCAnimation* animation=CCAnimation::create();  
      13.     animation->addSpriteFrameWithFileName("CloseNormal.png");  
      14.     animation->addSpriteFrameWithFileName("CloseSelected.png");  
      15.     animation->setDelayPerUnit(1.0f);  
      16.     CCAnimate* animate=CCAnimate::create(animation);  
      17.     CCRepeatForever* repeat=CCRepeatForever::create(animate);  
      18.     close->runAction(repeat);  
      19. }  

      (3)對(duì)于CCAnimation幀動(dòng)畫,可以設(shè)置循環(huán)屬性,而不使用CCRepeatForever。

      1. animation->setLoops(-1);  


      5.總結(jié)

      雖然CCRepeatForever也同樣繼承于CCActionInterval,理論上是延時(shí)動(dòng)作的子類,但是和一般的延時(shí)動(dòng)作又有很大的不同,所以平時(shí)在使用的時(shí)候必須很小心,不能當(dāng)成一般的CCActionInterval使用。而在cocos2d-x動(dòng)作的分類上是不是應(yīng)該把它從CCAction繼承出來會(huì)比較好一點(diǎn)?

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多