1. 程式人生 > >COCOS學習筆記--骨骼動畫

COCOS學習筆記--骨骼動畫

Cocos引擎中的骨骼動畫使用過程與序列幀動畫相同,一般都是先在Cocos Studio裡編輯動畫,然後在在工程程式碼中載入和使用動畫,這篇部落格就來詳細介紹下具體步驟:

一.使用CocosStudio編輯骨骼動畫

該過程步驟與使用CocosStudio編輯序列幀動畫相似,區別就是匯入的動畫資源與繫結的控制元件不同:

1.首先建立一個場景:檔案->新建檔案,名字叫“AnimationTest”:


2.向場景新增一個基礎容器,相當於一個層,並設定其座標、尺寸:

 

3.匯入骨骼動畫資源:這裡需要說明一下,動畫資源一共需要3個檔案:一個.ExportJson檔案,一個.plist檔案和一個.png檔案

。ExportJson檔案中記錄了骨骼動畫的描述資訊,plist檔案則是記錄碎圖整合成大圖後圖片的位置描述資訊,png檔案是整合的大圖。匯入時只需匯入ExportJson檔案,但這不意味著就不需要.plist檔案和一個.png檔案,如果沒有這兩個檔案匯入資源時就不會匯入成功。這幾個資源一般是由美工來編輯的,Cocos Studio新版本不支援編輯骨骼動畫的功能。

 

4.新增Armature控制元件:在左側的自定義控制元件中選取Armature控制元件,直接拖動到當前場景上即可,新建立的Armature控制元件會預設繫結一個牛仔的骨骼動畫,我們可以用自己的骨骼動畫來替換掉它。

              

5.將骨骼動畫資原始檔繫結到Armature控制元件上,也是直接拖動即可,將ExportJson檔案拖到Armature控制元件的“屬性”-“特性”-“檔案”中。另外,在“屬性”-“特性”-“動畫列表”下拉欄中可以看到該骨骼動畫的所有動作,每一個動作都有對應的名字,我這個骨骼動畫裡面有run、loading、attack、smitten、death等動作,它們的序號從0開始依次向後排,我們在程式碼中可以通過它們的動作名或序號來獲得這些動作。

 

6.編輯完骨骼動畫後要儲存和釋出專案,這樣會在我們的專案工程中Resources/res目錄下會生成一個AnimationTest.csb檔案,這個檔案就是我們所建立的這個場景的配置檔案,程式碼中就是通過載入這個檔案使用我們的骨骼動畫的。

 

二.在程式碼中使用Cocos Studio編輯的骨骼動畫

開啟專案工程檔案,在HelloWorldScene.cpp中新增程式碼。

首先要新增CCArmature.h的名稱空間:

using namespace cocostudio;

然後在HelloWorld::init()方法中修改程式碼:

1.播放我們編輯的骨骼動畫

//載入骨骼動畫所在場景的node
auto rootNode = CSLoader::createNode("AnimationTest.csb");
addChild(rootNode);
 
//獲得骨骼動畫
Armature* arm =(Armature*) rootNode->getChildByName("Panel_1")->getChildByName("ArmatureNode_1");
 
//播放骨骼動畫
//引數:1.動畫索引,起始為0 2.動畫之間是否有銜接幀 3.是否迴圈播放arm->getAnimation()->playWithIndex(2,-1,1);
 
//還可以通過動作名來播放動畫
arm->getAnimation()->play("run");
 

執行效果我就不弄動態的了吧,給大家截一張圖,反正可以看到我們的帥哥跑起來了:


2.此外,我們還可以給骨骼動畫添加回調函式

1).在標頭檔案中宣告骨骼動畫的回撥函式

void onMovementEvent(Armature* arm,MovementEventType type,const std::string&actionName);

給骨骼動畫添加回調函式後,當執行動畫時某些事件被觸發,其回撥函式內部就會被執行。你可能會想這些事件都是什麼呢?這裡我們看一下第二個引數MovementEventType的事件型別定義:

enum MovementEventType
{
    START,
    COMPLETE,
    LOOP_COMPLETE
};

可以看到,這3個事件型別分別為動作的開始、完成和迴圈完成,迴圈完成就是當動畫迴圈播放時每播放完一次會觸發一次的事件。另外,函式宣告中的第一個和第三個引數分別是骨骼動作的索引以及動作名稱。

2).繫結骨骼動畫的回撥函式

</pre><pre name="code" class="cpp">arm->getAnimation()->setMovementEventCallFunc(CC_CALLBACK_0(HelloWorld::onMovementEvent, this, 
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));

注意,繫結回撥函式用了setMovementEventCallFunc()方法,呼叫這個方法的執行者就是我們建立的Armature物件;該方法的引數是一個CC_CALLBACK_0巨集函式,此巨集函式的引數,前兩個為回撥函式以及回撥函式所屬類,後面3個具體是啥我還沒研究,反正是利用了C++11的某些新特性。

3).回撥函式的實現

這裡我只是用回撥函式打印出回撥事件型別以及骨骼動畫的動作名:

void HelloWorld::onMovementEvent(cocostudio::Armature *arm, cocostudio::MovementEventType type, const std::string &actionName)
{
    if (type == MovementEventType::START)
    {
        log("START");
    }
    if (type == MovementEventType::COMPLETE)
    {
        log("COMPLETE");
    }
    if (type == MovementEventType::LOOP_COMPLETE)
    {
        log("LOOP_COMPLETE");
    }
    log("name = %s", actionName.c_str());
}

列印結果如下:

 

可以看到,由於我們的這個骨骼動畫是迴圈播放的,每播放完一次都會執行一次回撥函式。我們可以利用骨骼動畫的回撥函式做很多事,比如播放受擊動畫時,播放結束後可以在其回撥函式中判斷主角是否還有血,如果沒血了就可播放其死亡動畫。所以說回撥函式就是給了我們一個時間點去操作一些邏輯。

 以上。