1. 程式人生 > >cocos2dx[2.x](19)--基本動畫CCAnimation/CCAnimate

cocos2dx[2.x](19)--基本動畫CCAnimation/CCAnimate

【嘮叨】

基本動畫製作需要用到CCAnimation類,用於儲存動畫相關的資訊。以及由CCActionInterval繼承的CCAnimate動畫動作。
還有一些在建立動畫動作的過程中,可能會用到的一些類CCSpriteFrame、CCSpriteFrameCache、CCAnimationFrame、CCAnimationCache。
有關快取類的詳細,參見《三種快取類》:http://shahdza.blog.51cto.com/2410787/1611766
本節的內容可能比較複雜,需要掌握的東西比較多,大家慢慢理解吧。。。

【小知識】

以下名詞術語對應的中文名,純屬自己歪歪,只是為了方便自己記憶罷了。i_f32.gif
CCSpriteFrame     :精靈幀。    它是相對動畫而產生的,其實就是一張紋理圖片。
CCAnimationFrame  :動畫幀。    由精靈幀與間隔幀陣列成,是動畫CCAnimation中的一幀。
CCSpriteFrameCache:精靈幀緩衝。用於存放精靈幀CCSpriteFrame的緩衝池。
CCAnimationCache  :動畫緩衝。  用於存放動畫CCAnimation的緩衝池。
delayPerUnit      :單位幀間隔。連續兩個動畫幀之間的時間間隔。單位:秒。
delayUnits        :間隔幀數。  當前動畫幀到下一個動畫幀需要等待的單位幀間隔的個數。

【3.x】
(1)去掉 “CC”
(2)SpriteFrameCache、AnimationCache 中獲得、釋放單例物件的方法:
使用getInstance() 替代 sharedSpriteFrameCache()
使用 destroyInstance() 替代 purgeSharedSpriteFrameCache()
(3)Animation 中一些引數的變化:
createWithSpriteFrames 中的引數 CCArray 改為 Vector

    //建立精靈幀CCSpriteFrame陣列
    //用於在內部建立動畫幀CCAnimationFrame,從而建立CCAnimation
CCArray* array = new CCArray(); //建立陣列 char str[] = "xxx.png"; CCSpriteFrame* frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(str); //從精靈幀緩衝池中獲取一個精靈幀 array->addObject(frame); //將精靈幀新增到陣列中
1.2、CCAnimationFrame動畫幀

說明:動畫幀就是在精靈幀的基礎之上,設定了到下一幀需要的間隔幀數,是動畫CCAnimation中的一幀。其中設定動畫幀的間隔幀數:setDelayUnits來完成的。
如:CCAnimation設定的單位幀間隔delayPerUnit = 0.2,
    而動畫幀的設定的間隔幀數DelayUnits = 10,
    那麼當前動畫幀到下一個動畫幀所需要延遲等待的時間間隔:0.2 * 10 = 2 秒。
    //建立動畫幀CCAnimationFrame陣列
        CCArray* array = new CCArray(); //建立陣列
        char str[] = "xxx.png";

        CCSpriteFrame* frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(str); //從精靈幀緩衝池中獲取一個精靈幀

        CCAnimationFrame* animationFrame = new CCAnimationFrame(); //建立動畫幀

        animationFrame->setSpriteFrame(frame); //設定精靈幀
        animationFrame->setDelayUnits(i);      //設定到下一動畫幀的間隔幀數

        array->addObject(animationFrame);      //將動畫幀新增到陣列
1.3、CCSpriteFrameCache精靈幀緩衝
    //將Animation/grossini.plist加入到精靈幀緩衝池中
    //也就是將動畫需要用到的批圖片加到緩衝池中
    //用於建立精靈幀
        CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Animation/grossini.plist");
1.4、CCAnimationCache動畫緩衝

通常情況下,對於一個精動畫,每次建立時都需要載入動畫幀,按順序新增到陣列,再建立對應的動畫CCAnimation類,這是一個非常煩瑣的計算過程。
對於使用頻率高的動畫,比如魚的遊動,將其加入快取可以有效降低每次建立的巨大消耗。
所欲將動畫CCAnimation直接放在動畫緩衝池中,當需要執行動畫動作時,就直接從動畫緩衝池中拿出來,去建立初始化CCAnimation會非常方便。
    //動畫命名為 Explosion,加入到動畫緩衝中
    CCAnimation* animation = CCAnimation::createWithSpriteFrames(arr,0.04);
    CCAnimationCache::sharedAnimationCache()->addAnimation(animation,"Explosion");

    //直接從緩衝池中取出 Explosion 動畫
    CCAnimation* animation = CCAnimationCache::sharedAnimationCache()->animationByName("Explosion");

2、CCAnimation

或許看了上面四個類後,大家可能會有點迷茫,接下來就將上面的類和CCAnimation關聯起來。

2.1、建立方法
/**
 *  總共有三種建立方法:
 *      (1)建立空動畫
 *      (2)使用精靈幀陣列建立
 *      (3)使用動畫幀陣列建立
 *  注意第二個方法是createWithSpriteFrames,而不是create。
 */
    //建立一個空動畫
    CCAnimation::create();

    //使用CCSpriteFrame精靈幀陣列,單位幀間隔delay秒
    //實際上在內部建立了動畫幀CCAnimationFrame,且間隔幀數為:1
    CCAnimation::createWithSpriteFrames(CCArray* arrayOfSpriteFrameNames, float delay = 0.0f);

    //使用CCAnimationFrame動畫幀陣列,單位幀間隔delayPerUnit秒,重複次數loops
    //其中loops:0為執行動畫;1為執行一次,……,-1為無限迴圈
    static CCAnimation* create(CCArray *arrayOfAnimationFrameNames, float delayPerUnit, unsigned int loops = 1);
2.2、新增動畫幀函式
/**
 *  總共有三種新增動畫幀的方法:
 *      (1)使用CCSpriteFrame
 *      (2)使用圖片資源(jpg,png等)
 *      (3)使用紋理圖片CCTexture2D
 *      (4)直接設定動畫幀陣列setFrames
 */
    //使用精靈幀來新增一個動畫幀,間隔幀數:1
    void addSpriteFrame(CCSpriteFrame *pFrame);

    //使用圖片資源(jpg,png等)來新增一個動畫幀,間隔幀數:1
    void addSpriteFrameWithFileName(const char *pszFileName);

    //從圖片紋理中擷取CCRect部分割槽域的圖片,間隔幀數:1
    void addSpriteFrameWithTexture(CCTexture2D* pobTexture, const CCRect& rect);

    //直接設定動畫幀CCAnimationFrames陣列
    void setFrames(CCArray* pAnimationFrames);
    CCArray* getFrames();
2.3、屬性設定

(1)單位幀間隔                     setDelayPerUnit
(2)設定動畫幀                     setFrames
(3)當動畫結束時,是否還原為第一幀 setRestoreOriginalFrame
(4)動畫重複執行次數               setLoops
/**
 *      單位幀間隔、間隔幀數、動畫總時間
 *      setDelayPerUnit , getTotalDelayUnits , getDuration
 */
    //設定單位幀間隔delayPerUnit秒
    void setDelayPerUnit(float);
    float getDelayPerUnit();

    //間隔幀數的總和totalDelayUnits
    //即:每個精靈幀到下一精靈幀的間隔幀數之和
    float getTotalDelayUnits(); 

    //動畫總時間:delayPerUnit * totalDelayUnits
    float getDuration();


/**
 *      其他屬性設定
 *      setFrames , setRestoreOriginalFrame , setLoops
 */
    //設定動畫幀CCAnimationFrames陣列
    void setFrames(CCArray* pAnimationFrames);
    CCArray* getFrames();

    //當動畫結束時,是否還原為第一幀
    void setRestoreOriginalFrame(bool);
    bool getRestoreOriginalFrame();

    //動畫執行次數
    //0表示不執行動畫,1表示執行1次,……,-1表示無限迴圈
    void setLoops(unsigned int );
    unsigned int getLoops();

3、CCAnimate

CCAnimate是用來真正執行CCAnimation動畫的動作類。
建立及使用方法如下:
    //使用CCAnimation建立CCAnimate
    CCAnimate* animate = CCAnimate::create(animation);
    sprite->runAction(animate); //執行動畫動作

【程式碼實戰】

程式碼資源來自官方TestCpp。
下面例舉建立動畫動作CCAnimation/CCAnimate的三種方式。

1、圖片資源
這裡寫圖片描述

2、直接使用圖片資源

    每個動畫幀的間隔幀數均為: 1
    單位幀間隔              : 2.0/14.0 秒
    連續兩動畫幀的時間間隔為: 2.0/14.0 * 1 秒
//建立精靈sprite
    CCSprite* sprite = CCSprite::create("Animation/dance_00.png");
    sprite->setPosition( mysize/2 );
    this->addChild(sprite);


//建立CCAnimation
    CCAnimation* animation = CCAnimation::create();

    //直接新增圖片資源
    for(int i =1; i <= 14; i++) {
        char str[50];
        sprintf(str, "Animation/dance_%02d.png", i);

        animation->addSpriteFrameWithFileName(str); //新增動畫幀
    }

    //設定屬性
    animation->setRestoreOriginalFrame(true); //還原第一幀
    animation->setDelayPerUnit(2.0/14.0);     //單位幀間隔
    animation->setLoops(-1);                  //-1無限迴圈

//建立CCAnimate
    CCAnimate* animate = CCAnimate::create(animation);

//執行動畫動作
    sprite->runAction(animate);

3、使用精靈幀

    每個動畫幀的間隔幀數均為: 1
    單位幀間隔              : 2.0/14.0 秒
    連續兩動畫幀的時間間隔為: 2.0/14.0 * 1 秒
    注意:使用精靈幀陣列建立CCAnimation時,是createWithSpriteFrames,不是create。
//建立精靈sprite
    CCSprite* sprite = CCSprite::create("Animation/dance_00.png");
    sprite->setPosition( mysize/2 );
    this->addChild(sprite);


//建立CCAnimation
    //將plist批處理的多張圖片,新增到精靈幀緩衝池中
    CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Animation/grossini.plist");

    //建立精靈幀CCSpriteFrame陣列
    CCArray* array = new CCArray();
    for(int i =1; i <= 14; i++) {
        char str[50];
        sprintf(str, "grossini_dance_%02d.png", i);

        CCSpriteFrame* frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(str);
        array->addObject(frame);
    }

    //使用精靈幀陣列建立,單位幀間隔為2.0/14.0秒
    CCAnimation* animation = CCAnimation::createWithSpriteFrames(array, 2.0/14.0);

    //屬性設定
    animation->setRestoreOriginalFrame(true); //還原第一幀
    animation->setLoops(-1);                  //無線迴圈


//建立CCAnimate
    CCAnimate* animate = CCAnimate::create(animation);


//執行動畫動作
    sprite->runAction(animate);

4、使用動畫幀

    每個動畫幀的間隔幀數均為: 1
    單位幀間隔              : 0.2 秒
    連續兩動畫幀的時間間隔為: 0.2 * i 秒(第i個動畫幀到第i+1個動畫幀的延遲時間)
//建立精靈sprite
    CCSprite* sprite = CCSprite::create("Animation/dance_00.png");
    sprite->setPosition( mysize/2 );
    this->addChild(sprite);


//建立CCAnimation
    //將plist批處理的多張圖片,新增到精靈幀緩衝
    CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Animation/grossini.plist");

    //建立動畫幀CCAnimationFrame陣列
    CCArray* array = new CCArray();
    for(int i =1; i <= 14; i++) {
        char str[50];
        sprintf(str, "grossini_dance_%02d.png", i);

        CCSpriteFrame* frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(str);
        CCAnimationFrame* animationFrame = new CCAnimationFrame();

        animationFrame->setSpriteFrame(frame); //設定精靈幀
        animationFrame->setDelayUnits( i );    //設定間隔幀數

        array->addObject(animationFrame);
    }

    //使用動畫幀陣列建立,單位幀間隔0.2秒
    CCAnimation* animation = CCAnimation::create(array, 0.2f);
    animation->setRestoreOriginalFrame(true);
    animation->setLoops(-1);


//建立CCAnimate
    CCAnimate* animate = CCAnimate::create(animation);


//執行動畫動作
    sprite->runAction(animate);

5、執行結果
這裡寫圖片描述

6、分析與總結

(1)仔細觀察一下第三個和前兩個有什麼區別?是不是動作執行越來越緩慢了?因為最後一張是用動畫幀建立的,並且我設定了每個動畫幀的間隔幀數都不一樣,所以會有如上的效果。
(2)更多的使用方法,自行琢磨,加油!