cocos2dx版本為3.10
1.在使用spine的過程中,發現了一個比較嚴重的問題:每次創建SkeletonAnimation的時候都會很卡,即使是使用同一個骨骼數據skeletonData。
跟蹤代碼發現,在每次調用函數spine::SkeletonAnimation::createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);的時候都需要重新解析一次skeletonDataFile產生骨骼數據skeletonData。
2.問題找到了,那要想個最簡單的解決辦法,就是將骨骼數據skeletonData緩存起來,需要的時候再取出來使用。
3.直接修改SkeletonAnimation的源碼
①在頭文件SkeletonAnimation.h中增加對應函數以及成員變量
1 public: 2 //從緩存中創建Animation 3 static SkeletonAnimation* createFromCache(const std::string& skeletonDataKeyName); 4 5 //將文件讀入到cache中(skeletonDataKeyName參數為自定義的骨骼數據名稱) 6 static spSkeletonData* readSkeletonDataToCache(const std::string& skeletonDataKeyName, const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1); 7 8 //從cache中得到skeletonData(skeletonDataKeyName參數為自定義的骨骼數據名稱) 9 static spSkeletonData* getSkeletonDataFromCache(const std::string& skeletonDataKeyName); 10 11 //從cache中刪除skeletonData(skeletonDataKeyName參數為自定義的骨骼數據名稱) 12 static bool removeSkeletonData(const std::string& skeletonDataKeyName); 13 14 //清理所有skeletonData 15 static void removeAllSkeletonData(); 16 17 //是否在cache中存在對應的骨骼數據skeletonData 18 static bool isExistSkeletonDataInCache(const std::string& skeletonDataKeyName); 19 private: 20 struct SkeletonDataInCache{ 21 spSkeletonData* _skeleton_data; //記錄骨骼數據 22 spAtlas* _atlas; //記錄對應圖片塊信息 23 }; 24 typedef std::map<std::string, SkeletonDataInCache>::iterator ItSkeletonData; 25 static std::map<std::string, SkeletonDataInCache> _all_skeleton_data_cache; //記錄所有的skeletonData緩沖區
②在源文件SkeletonAnimation.cpp中增加對應函數實現以及初始化靜態成員變量
1 SkeletonAnimation* SkeletonAnimation::createFromCache(const std::string& skeletonDataKeyName) 2 { 3 if (spSkeletonData* skeleton_data = getSkeletonDataFromCache(skeletonDataKeyName)){ 4 SkeletonAnimation* node = new SkeletonAnimation(skeleton_data, false); 5 node->autorelease(); 6 return node; 7 } 8 9 return nullptr; 10 } 11 12 spSkeletonData* SkeletonAnimation::readSkeletonDataToCache(const std::string& skeletonDataKeyName, const std::string& skeletonDataFile, const std::string& atlasFile, float scale /*= 1*/) 13 { 14 ItSkeletonData it = _all_skeleton_data_cache.find(skeletonDataKeyName); 15 16 if (it == _all_skeleton_data_cache.end()){ 17 SkeletonDataInCache skeleton_data_in_cache; 18 skeleton_data_in_cache._atlas = nullptr; 19 skeleton_data_in_cache._skeleton_data = nullptr; 20 21 skeleton_data_in_cache._atlas = spAtlas_createFromFile(atlasFile.c_str(), 0); 22 CCASSERT(skeleton_data_in_cache._atlas, "readSkeletonDataToCachereading Error atlas file."); 23 24 spSkeletonJson* json = spSkeletonJson_create(skeleton_data_in_cache._atlas); 25 json->scale = scale; 26 skeleton_data_in_cache._skeleton_data = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile.c_str()); 27 CCASSERT(skeleton_data_in_cache._skeleton_data, json->error ? json->error : "readSkeletonDataToCache Error reading skeleton data file."); 28 spSkeletonJson_dispose(json); 29 30 if (skeleton_data_in_cache._atlas && skeleton_data_in_cache._skeleton_data){ 31 _all_skeleton_data_cache[skeletonDataKeyName] = skeleton_data_in_cache; 32 33 return skeleton_data_in_cache._skeleton_data; 34 } 35 else{ //錯誤處理,釋放創建的資源 36 if (skeleton_data_in_cache._skeleton_data){ 37 spSkeletonData_dispose(skeleton_data_in_cache._skeleton_data); 38 } 39 40 if (skeleton_data_in_cache._atlas){ 41 spAtlas_dispose(skeleton_data_in_cache._atlas); 42 } 43 } 44 } 45 46 return nullptr; 47 } 48 49 spSkeletonData* SkeletonAnimation::getSkeletonDataFromCache(const std::string& skeletonDataKeyName) 50 { 51 ItSkeletonData it = _all_skeleton_data_cache.find(skeletonDataKeyName); 52 if (it != _all_skeleton_data_cache.end()){ 53 return it->second._skeleton_data; 54 } 55 56 return nullptr; 57 } 58 59 bool SkeletonAnimation::removeSkeletonData(const std::string& skeletonDataKeyName) 60 { 61 ItSkeletonData it = _all_skeleton_data_cache.find(skeletonDataKeyName); 62 if (it != _all_skeleton_data_cache.end()){ 63 if (it->second._skeleton_data) spSkeletonData_dispose(it->second._skeleton_data); 64 if (it->second._atlas) spAtlas_dispose(it->second._atlas); 65 66 _all_skeleton_data_cache.erase(it); 67 return true; 68 } 69 70 return false; 71 } 72 73 void SkeletonAnimation::removeAllSkeletonData() 74 { 75 for (ItSkeletonData it = _all_skeleton_data_cache.begin(); it != _all_skeleton_data_cache.end(); ++it){ 76 if (it->second._skeleton_data) spSkeletonData_dispose(it->second._skeleton_data); 77 if (it->second._atlas) spAtlas_dispose(it->second._atlas); 78 } 79 80 _all_skeleton_data_cache.clear(); 81 } 82 83 bool SkeletonAnimation::isExistSkeletonDataInCache(const std::string& skeletonDataKeyName) 84 { 85 ItSkeletonData it = _all_skeleton_data_cache.find(skeletonDataKeyName); 86 if (it != _all_skeleton_data_cache.end()){ 87 return true; 88 } 89 90 return false; 91 } 92 93 std::map<std::string, SkeletonAnimation::SkeletonDataInCache> SkeletonAnimation::_all_skeleton_data_cache; //初始化靜態成員
4.好了,重新編譯libcocos2d後,下面為c++的使用方式。
①在需要使用的地方調用對應的接口進行創建
1 //判斷是否存在自定義名稱為GirlSkeletonDataKey的骨骼數據 2 spSkeletonData* skeleton_data = spine::SkeletonAnimation::getSkeletonDataFromCache("GirlSkeletonDataKey"); 3 4 //如果不存在對應的骨骼數據,則讀入解析一遍 5 if (!skeleton_data){ 6 skeleton_data = spine::SkeletonAnimation::readSkeletonDataToCache("GirlSkeletonDataKey", "girl.json", "girl.atlas"); 7 } 8 9 if (skeleton_data){ 10 //直接使用骨骼數據創建動畫 11 spine::SkeletonAnimation* skeleton_animation = SkeletonAnimation::createWithData(skeleton_data); 12 13 //也可以使用這個接口,效果和createWithData一樣 14 //spine::SkeletonAnimation* skeleton_animation = SkeletonAnimation::createFromCache("GirlSkeletonDataKey"); 15 }
②在需要釋放數據的地方調用這個接口釋放所有的骨骼數據緩存數據
1 spine::SkeletonAnimation::removeAllSkeletonData();
5.lua使用方式
①直接進入cocos2d-x-3.10\tools\tolua,運行genbindings.py來重新生成c++和lua之間的綁定文件
②重新編譯libluacocos2d
③下面為lua的使用方式
1 --由於lua中沒有綁定spSkeletonData,所以readSkeletonDataToCache的函數返回值無效(getSkeletonDataFromCache函數也一樣),不能對返回值進行判斷! 2 if not sp.SkeletonAnimation:isExistSkeletonDataInCache("GirlSkeletonDataKey") then 3 sp.SkeletonAnimation:readSkeletonDataToCache("GirlSkeletonDataKey", "girl.json", "girl.atlas"); 4 end 5 --由於cocos2dx_spine.ini中沒對SkeletonAnimation::createWithData函數進行綁定,所以這個函數在lua中不能使用 6 local skeleton_animation = sp.SkeletonAnimation:createFromCache("GirlSkeletonDataKey");
以上,完。