在cocos2d-x中使用DragonBones實現骨骼動畫

基礎知識

要看懂本文,你需要了解骨骼動畫(或稱關節動畫)是什麼,以及DragonBones是什麼。下面提供了一些資料:

To flash veteran: do you remember the ‘Moho’?

不要使用官方版本的DragonBones

在寫這篇文章的時候,DragonBones的官方版本爲v2.3。cocos2d-x的穩定版本爲2.1.5。

爲了使用cocos2d-x,我們需要選擇 Zip(XML and PNGs) 的方式,將圖像文件導出爲獨立的圖像幀加上XML格式的元數據文件。官方版本的DragonBones,會將元數據分成texture.xml和skeleton.xml兩個文件,而cocos2d-x目前不支持這種情況。

因此,我們需要使用修改過的DragonBones插件。在CocoStudio的官方論壇中提供了一個這樣的插件,版本是2.0。但這個插件有一個bug,我在2.2的基礎上重新打包了插件,並修復了bug。詳情看這裏:cocos2d-x專用的DragonBones2.2 。

使用這個版本的插件,在導出圖像文件的時候,會將texture.xml和skeleton.xml文件合併成1個,同時會修改元數據中的部分格式,使其滿足cocos2d-x的解析庫要求。

注意:下面提到DragonBones的時候,均指這個修改過的插件。

DragonBones輸出的圖像數據可以導入CocoStudio Action編輯器

可以使用CocoStudio的Action編輯器將DragonBones輸出的圖片導入,然後重新輸出成Cocos2d-x支持的格式。這種格式包含一個把碎圖拼接好的png文件,一個plist文件和一個json文件。

如何進行上面的導入操作?可以看這個視頻:flash插件 DragonBone導出以及CocoStudio動畫編輯器的導入

使用CocoStudio的Action編輯器導出的格式有什麼優勢呢?

  • DragonBones輸出的png是碎圖,而CocoStudio Action編輯器將碎圖拼接成大圖了;
  • plist文件是png碎圖拼接的metadata;
  • json文件是骨骼和動畫信息。

但是,使用CocoStudio Action編輯器有幾個問題:

  • 莫名其妙的崩潰。在導入的DragonBones文件中包含空格、中文等內容的時候,編輯器經常直接退出,讓人較難判斷原因;
  • 不支持DragonBones的層級關係。如果在DragonBones中設計了層級關係,那麼CocoStudio無法識別,骨骼會發生很大的錯位;
  • CocoStudio Action編輯器不穩定。我在0.3.0.0版本中,可以導入DragonBones格式,但使用0.3.2.0,又不能導入同樣的格式了,編輯器直接退出。

爲什麼不用CocoStudio

既然導入有這樣那樣的問題,那麼直接用CocoStudio做骨骼動畫好了,幹嗎還要用DragonBones?

DragonBones有如下優勢:

  • DragonBones的骨骼動畫實現起來非常非常容易;
  • 大多數做動畫的同學都熟悉Flash,但極少知道CocoStudio,誰都願意用自己熟悉的軟件;
  • Flash和DragonBones的操作體驗優於CocoStudio太多。

加上上面提到的不穩定原因,我也無法說服自己使用CocoStudio Action編輯器,更別說把它交給美術MM了。

更何況,我們根本不必把DragonBones生成的文件導入CocoStudio!cocos2d-x能直接支持DragonBones生成的文件!

如果你還是希望用CocoStudo來做骨骼動畫,可以參考這篇文章:使用 CocoStudio 創建 Cocos2d-x 序列幀和骨骼動畫

2013-10-11 update CocoStudio升級到1.0之後,已經支持導入fla文件,但這個導入是有限制的:

  1. 需要將 想要導入到動畫編輯器的元件放入到主場景中
  2. 暫時不支持導入矢量圖形,可以右鍵矢量圖形 裝換爲位圖
  3. 暫不支持嵌套元件的元件作爲骨骼部件

這篇帖子詳細介紹了這個限制 ,也有允許導入的文件範例。

生成cocos2d-x支持的文件格式

上面已經提到,使用DragonBones可以生成一堆碎圖文件和一個xml文件。我們首先要做的,就是把這堆碎圖文件拼成一張大圖。cocos2d-x支持plist格式(基於XML)的元數據。

當然,如果你使用我修改過的 cocos2d-x專用的DragonBones2.2, 就不必進行下面的拼合工作,它會自動幫你生成png/xml/plist文件。

你也可以選擇 Sprite Packer(免費) 或者 Texture Packer 來做拼合碎圖以及生成plist文件的工作。Sprite Sheet Editor 正在準備支持cocos2d的plist文件格式。

拼合成功後,可以將碎圖刪除,現在我們有3個文件(爲了方便描述,這裏假設主文件名均爲skeleton):

  1. 拼合後的大的png文件 skeleton.png;
  2. plist元數據文件 skeleton.plist;
  3. xml骨骼動畫數據文件 skeleton.xml。

再次強調,這裏讓主文件相同只是爲了方便描述,實際使用的時候,主文件不必相同。

但是(爲什麼非要有但是呢?),你不認爲文件名相同更方便人類閱讀麼?

我先來說一下 skeleton.xml 的內部結構吧。下面是我用 DragonBones 官方提供的 Dragon.fla 生成的xml文件……呃……的一部分。

?View Code XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<skeleton version="2.1" frameRate="24" name="Dragon">
    <armatures>
        <armature name="Dragon">
            <!-- 這裏是一坨b 那啥~ b標籤(表想不正……) -->
        </armature>
    </armatures>
    <animations>
        <animation name="Dragon">
            <!-- 這裏是一坨mov -->
        </animation>
    </animations>
    <TextureAtlas name="Dragon" height="512" width="512">
        <!-- 這裏是一坨SubTexture -->
    </TextureAtlas>
</skeleton>

好了,1和2不必再檢查了。但 skeleton.xml 必須檢查。如果你不希望和我一樣耗費一下午來猜謎的話,就記住下面幾點吧:

  1. 最新的測試標明,armatures是允許有多個子標籤的,只要與animations中的子標籤對應即可。armature標籤只允許有一個。你生成的xml文件中,可能由於FLA製作的問題,在armatures下面有多個armature,這是絕對不行DI。cocos2d-x碰到這種情況會直接異常沒商量。所以,留一個最終正確的吧!
  2. armature和animation的name屬性必須完全相同,這個名稱將是cocos2d-x中最終使用的名稱。
  3. TextureAtlas的name屬性和skeleton的name屬性就無所謂啦,可以隨便填了。
  4. 還是有必要再羅嗦一遍,各種name不要用中文,不要加空格,不要用特殊字符……grumble,grumble……

話說,爲什麼生成的xml文件中會有多個armature呢?借勢淫威……你的FLA庫中的某個MovieClip中的第一層中包含label!

我們知道(我不知道你知不知道,你知道你就是我們知道中的我們,你不知道你就不是我們知道中的我們),DragonBones會將MovieClip第一層的label當作骨骼動畫中的不同動作。如果你某個不開眼的MovieClip中莫名其妙的加了一個不知所謂的label,而且你這個MovieClip又被製作動畫的那個主MovieClip使用了,那麼這個帶有label的MovieClip也會被作爲armature輸出。

使用CCArmature包實現骨骼動畫

終於特碼嘚進入代碼階段了,我快要累死了。

CCArmature並不是cocos2d-x核心包的內容,你可以在 cocos2d-x/extensions 中找到它。

在頭文件中,需要include CCArmature包的所有內容。我不明白爲什麼 cocos2d-x 開發組不把這些包含文件都放到 cocos-ext.h 中去。畢竟 spine 都被放進去了啊。難道是不穩定?不敢再往下想了,一定有陰謀,借勢個陰謀……

?View Code CPP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "cocos2d.h"
#include "cocos-ext.h"
#include "VisibleRect.h"
 
#include "CCArmature/CCArmature.h"
#include "CCArmature/CCBone.h"
#include "CCArmature/animation/CCArmatureAnimation.h"
#include "CCArmature/datas/CCDatas.h"
#include "CCArmature/display/CCBatchNode.h"
#include "CCArmature/display/CCDecorativeDisplay.h"
#include "CCArmature/display/CCDisplayManager.h"
#include "CCArmature/display/CCSkin.h"
#include "CCArmature/physics/CCColliderDetector.h"
#include "CCArmature/physics/CCPhysicsWorld.h"
#include "CCArmature/utils/CCArmatureDataManager.h"
#include "CCArmature/utils/CCConstValue.h"
#include "CCArmature/utils/CCDataReaderHelper.h"
#include "CCArmature/utils/CCTweenFunction.h"
#include "CCArmature/external_tool/sigslot.h"

2013-10-12 update 現在陰謀終於展現了,原來cocos2d-x 2.2.0 把 CCArmature 整合進入了extensions/CocoStudio 包。下面的內容出現在 cocos-ext.h 中:

?View Code CPP
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "CocoStudio/Armature/CCArmature.h"
#include "CocoStudio/Armature/CCBone.h"
#include "CocoStudio/Armature/animation/CCArmatureAnimation.h"
#include "CocoStudio/Armature/datas/CCDatas.h"
#include "CocoStudio/Armature/display/CCBatchNode.h"
#include "CocoStudio/Armature/display/CCDecorativeDisplay.h"
#include "CocoStudio/Armature/display/CCDisplayManager.h"
#include "CocoStudio/Armature/display/CCSkin.h"
#include "CocoStudio/Armature/physics/CCColliderDetector.h"
#include "CocoStudio/Armature/utils/CCArmatureDataManager.h"
#include "CocoStudio/Armature/utils/CCDataReaderHelper.h"
#include "CocoStudio/Armature/utils/CCTweenFunction.h"
#include "CocoStudio/Armature/external_tool/sigslot.h"

那麼,如果你使用cocos2d-x 2.2.0(或以上),只需要 #include "cocos-ext.h" 即可了。

然後:

  • 載入資源、創建動畫、播放第一個動畫。
  • VisibleRect這個類可以在 TestCpp 範例中找到。
  • 我寫得簡單,是因爲我只說重點和易錯的地方。
  • 埋怨我寫的簡單的,可以直接查看 TestCpp/ExtensionsTest/ArmatureTest 範例,那個詳細得令人髮指。

2013-10-12 update 在 cocos2d-x 2.2.0 中,應該查看 ExtensionsTest/CocoStudioArmatureTest 範例。

?View Code CPP
1
2
3
4
5
CCArmatureDataManager::sharedArmatureDataManager()->addArmatureFileInfo("skeleton.png", "skeleton.plist", "skeleton.xml");
CCArmature* __armature = CCArmature::create("Dragon");
__armature->getAnimation()->playByIndex(0);
__armature->setPosition(VisibleRect::center().x, VisibleRect::center().y*0.3f);
addChild(__armature)

Cocos2d-x 2.2.0 在 CCArmature 上的BUG

比較 Cocos2d-x 2.1.5 和 Cocos2d-2.2.0,它們的CCArmature播放效果不同。

原本在2.1.5上非常流暢的Armature的骨骼動畫,在2.2.0上會出現卡頓,以及動作不協調等情況。這不是幀率的問題,應該是在修改的過程中,Armature的Tween出了問題。

我分析出現這個BUG的原因應該是這樣的:

  • CCArmature其實是基於DragonBones2.1的庫移植而來,就是用C++把ActionScript3代碼庫重寫了一遍;
  • 現在觸控傳媒希望大力推進CocoStudio的使用(目前是lite版,可能以後會出收費版),讓CocoStudio去支持CCArmature骨骼動畫,因此不斷對CCArmature進行改進以支持CocoStudio生成的JSON文件格式;
  • 在改進的過程中,可能因爲某些失誤,導致對原來的DragonBones格式的支持出現了問題;
  • 由於這次改進僅針對CocoStudio導出的JSON格式,而沒有測試DragonBones生成的格式,導致這個BUG在2.2.0發佈的時候也沒有得到解決;
  • cocos2d-x在各種大會上說支持Flash,讓Flash成爲cocos2d-x的編輯器,其實團隊內並不是真正重視Flash,或者並沒有安排Flash的相關測試;
  • 對於Cocos2d-x的使用者來說,深入瞭解Flash的可能比較少,更少人知道CCArmature其實是來自DragonBones,使用DragonBones的就少得可憐。再加上網上的資源匱乏,舊的、被轉帖的教程氾濫,描述正確且準確的教程缺失,這個BUG就很難發現;

以上全是我的猜測。

但即使是官方的TestCPP,如果測試DragonBones導出的Dragon那個Armature動畫,也是能看出問題的。下面是動畫,請注意尾部頂端、右臂以及腿的動作區別(這兩個gif文件很大,要稍微等一會兒纔會播放流暢):

For v2.2.0 testcpp/ExtensionsTest/CocoStudioArmatureTest

For v2.1.5 testcpp/ExtensionsTest/ArmatureTest

這個BUG我已經在 Cocos2d-x官網提出 bug#2887 ,不過開發團隊似乎只測試了CocoStudio導出的格式情況,並且認爲並無問題。我補發了TestCpp的測試視頻,官方並未回覆。

2013-10-15 update 根據開發團隊的最新回覆,此BUG已經被確認,並指定目標版本爲3.0alpha-1。看來要等一段時間了。在官方解決這個BUG之前,我只能使用2.1.5版本。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章