editor-support -> cocostudio文件夾中,win下通過篩選器,文件結(jié)構(gòu)如下。(mac下沒有分,是整個一坨) armature(目錄): animation(目錄):動畫控制相關(guān)。 CCProcessBase(文件): ProcessBase" />

国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

cocos2dx骨骼動畫Armature源碼剖析(三)_javascript技巧

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 21:43:26
文檔

cocos2dx骨骼動畫Armature源碼剖析(三)_javascript技巧

cocos2dx骨骼動畫Armature源碼剖析(三)_javascript技巧:cocos2dx里骨骼動畫代碼在cocos -> editor-support -> cocostudio文件夾中,win下通過篩選器,文件結(jié)構(gòu)如下。(mac下沒有分,是整個一坨) armature(目錄): animation(目錄):動畫控制相關(guān)。 CCProcessBase(文件): ProcessBase
推薦度:
導(dǎo)讀cocos2dx骨骼動畫Armature源碼剖析(三)_javascript技巧:cocos2dx里骨骼動畫代碼在cocos -> editor-support -> cocostudio文件夾中,win下通過篩選器,文件結(jié)構(gòu)如下。(mac下沒有分,是整個一坨) armature(目錄): animation(目錄):動畫控制相關(guān)。 CCProcessBase(文件): ProcessBase
cocos2dx里骨骼動畫代碼在cocos -> editor-support -> cocostudio文件夾中,win下通過篩選器,文件結(jié)構(gòu)如下。(mac下沒有分,是整個一坨)

數(shù)據(jù)相關(guān)源碼

從底層到高層分析一個類一個類分析

再來看下數(shù)據(jù)相關(guān)的UML,總體來說,就是ArmatureDataManager依賴DataReaderHelper把flash導(dǎo)出的xml文件解析成程序直接用的XXData,XXData對應(yīng)于xml的某個節(jié)點,比如FrameData就對應(yīng)于節(jié)點()。

BaseData

BaseData:用來表示骨骼或幀的位置、旋轉(zhuǎn)、顏色、縮放。

作為FrameData和BoneData的基類,提供骨骼的狀態(tài)信息。從下文可知BoneData對應(yīng)xml中的>中的b節(jié)點,F(xiàn)rameData對應(yīng)xml中的節(jié)點,BoneData和FrameData都有

等屬性,BaseDa代表了這些屬性。

BoneData

BoneData對應(yīng)xml中的>中的b節(jié)點

BoneData里有displayDataList,用來放這個骨頭上的皮膚(就是DisplayData), DisplayData對應(yīng)xml節(jié)點中的>節(jié)點,一個BoneData里可以有多個皮膚,換裝等功能需要多個皮膚。

FrameData

FrameData對應(yīng)xml中的節(jié)點,就是flash里的關(guān)鍵幀信息。

DisplayData

DisplayData是SpriteDisplayData、ArmatureDisplayData、ParticleDisplayData的父類,用來表示展示節(jié)點信息。

ArmatureData

ArmatureData是對應(yīng)節(jié)點,里面有這個骨骼的所有骨頭,可以看成骨骼動畫的骨骼。

AnimationData

AnimationData對應(yīng)節(jié)點,里面有多個MovementData,MovementData(下面介紹)對應(yīng)xml中的mov,為flash中的一個帶幀標(biāo)簽的動畫。

MovementData

MovementData對應(yīng)xml中>, 其中有所有的帶幀信息的骨骼MovementBoneData(mov中的b)。

MovementBoneData

MovementBoneData對應(yīng)xml中>的b,里面有frameList,即為關(guān)鍵幀信息。

小總結(jié)

xml中的各個節(jié)點和XXData的對應(yīng)關(guān)系如下表,xml各個字段的意義可以參考上篇文章

再來看產(chǎn)生動畫相關(guān)的代碼

ArmatureDataManager

ArmatureDataManager利用DataReaderHelper解析出armarureDatas、animationDatas和_textureDatas。

ArmatureDataManager是個單例,用到動畫時會到ArmatureDataManager取得要生成動畫的數(shù)據(jù)。

 class ArmatureDataManager : public cocosd::Ref
 {
 public:
 //單例 
 static ArmatureDataManager *getInstance();
 static void destroyInstance();
 public:
 void addArmatureData(const std::string& id, ArmatureData *armatureData, const std::string& configFilePath = "");
 ArmatureData *getArmatureData(const std::string& id);
 void removeArmatureData(const std::string& id);
 void addAnimationData(const std::string& id, AnimationData *animationData, const std::string& configFilePath = "");
 AnimationData *getAnimationData(const std::string& id);
 void removeAnimationData(const std::string& id);
 void addTextureData(const std::string& id, TextureData *textureData, const std::string& configFilePath = "");
 TextureData *getTextureData(const std::string& id);
 void removeTextureData(const std::string& id);
 void addArmatureFileInfo(const std::string& configFilePath);
 const cocosd::Map& getArmatureDatas() const;
 const cocosd::Map& getAnimationDatas() const;
 const cocosd::Map& getTextureDatas() const;
 protected:
 void addRelativeData(const std::string& configFilePath);
 RelativeData *getRelativeData(const std::string& configFilePath);
 private:
 cocosd::Map _armarureDatas;
 cocosd::Map _animationDatas;
 cocosd::Map _textureDatas;
 std::unordered_map _relativeDatas;
 };

主要就是armarureDatas、animationDatas、_textureDatas三個map,那這三個map是怎么產(chǎn)生的呢?當(dāng)執(zhí)行


后,那三個map變生成了。addArmatureFileInfo代碼如下

又調(diào)用了DataReaderHelper::getInstance()->addDataFromFile(),可知是DataReaderHelper真正完成了數(shù)據(jù)的解析。

DataReaderHelper類里有一堆decodeXXX()(比如decodeArmature、decodeBone)解析xml的某個節(jié)點。看下

addDataFromFile這個代碼:

對應(yīng)不同的文件(xml、json、二進制)解析方式,xml用到是addDataFromCache

里面有三個while,分別decodeArmature、decodeAnimation、decodeTexture,生成ArmatureData、AnimationData、TextureData之后又ArmatureDataManager::getInstance()->addArmatureData、addAnimationData、addTextureData,加到ArmatureDataManager對應(yīng)map里。decodeXXX里又會調(diào)用各種decodeXX來生成相應(yīng)的XXXData。

Armature

在載入了xml數(shù)據(jù)后,調(diào)用

便展示了動畫,那么這是如何做到的呢?

Armature部分代碼如下,ArmatureAnimation控制xml的mov節(jié)點,Bone中有Tween,這個Tween對應(yīng)xml中b(MovementBoneData)

class Armature: public cocosd::Node, public cocosd::BlendProtocol {
 protected:
 //要展示動畫的ArmatureData
 ArmatureData *_armatureData;
 BatchNode *_batchNode;
 Bone *_parentBone;
 float _version;
 mutable bool _armatureTransformDirty;
 //所有Bone
 cocosd::Map _boneDic; cocosd::Vector _topBoneList;
 
 cocosd::BlendFunc _blendFunc; 
 cocosd::Vec _offsetPoint;
 cocosd::Vec _realAnchorPointInPoints;
 //動畫控制器
 ArmatureAnimation *_animation;
 };

Bone

部分代碼如下,tweenData為當(dāng)前Bone的狀態(tài),每幀都會更新這個值,并用tweenData確定worldInfo,提供Skin顯示信息。tween為骨頭的整個動畫過程。

class Bone: public cocosd::Node {
 protected:
 BoneData *_boneData;
 
 //! A weak reference to the Armature
 Armature *_armature;
 
 //! A weak reference to the child Armature
 Armature *_childArmature;
 
 DisplayManager *_displayManager;
 
 /*
 * When Armature play an animation, if there is not a MovementBoneData of this bone in this MovementData, this bone will be hidden.
 * Set IgnoreMovementBoneData to true, then this bone will also be shown.
 */
 bool _ignoreMovementBoneData;
 
 cocosd::BlendFunc _blendFunc;
 bool _blendDirty;
 
 Tween *_tween; //! Calculate tween effect
 
 //! Used for making tween effect in every frame
 FrameData *_tweenData;
 
 Bone *_parentBone; //! A weak reference to its parent
 bool _boneTransformDirty; //! Whether or not transform dirty
 
 //! self Transform, use this to change display's state
 cocosd::Mat _worldTransform;
 
 BaseData *_worldInfo;
 
 //! Armature's parent bone
 Bone *_armatureParentBone;
 
 };

Tween

這個是每個骨頭的動畫過程,見下面的movementBoneData。tweenData是Bone中tweenData的引用,在這每幀會計算這個tweenData值。

class Tween : public ProcessBase{
 protected:
 //! A weak reference to the current MovementBoneData. The data is in the data pool
 MovementBoneData *_movementBoneData;
 
 FrameData *_tweenData; //! The computational tween frame data, //! A weak reference to the Bone's tweenData
 FrameData *_from; //! From frame data, used for calculate between value
 FrameData *_to; //! To frame data, used for calculate between value
 
 // total diff guan
 FrameData *_between; //! Between frame data, used for calculate current FrameData(m_pNode) value
 
 Bone *_bone; //! A weak reference to the Bone
 
 TweenType _frameTweenEasing; //! Dedermine which tween effect current frame use
 
 int _betweenDuration; //! Current key frame will last _betweenDuration frames
 
 // 總共運行了多少幀 guan
 int _totalDuration;
 
 int _fromIndex; //! The current frame index in FrameList of MovementBoneData, it's different from m_iFrameIndex
 int _toIndex; //! The next frame index in FrameList of MovementBoneData, it's different from m_iFrameIndex
 
 ArmatureAnimation *_animation;
 
 bool _passLastFrame; //! If current frame index is more than the last frame's index
 };

ArmatureAnimation

控制動畫的播放,看到_tweenList,所有骨頭的集合就是動畫了。

class ArmatureAnimation : public ProcessBase {
protected:
 //! AnimationData save all MovementDatas this animation used.
 AnimationData *_animationData;

 MovementData *_movementData; //! MovementData save all MovementFrameDatas this animation used.

 Armature *_armature; //! A weak reference of armature

 std::string _movementID; //! Current movment's name

 int _toIndex; //! The frame index in MovementData->m_pMovFrameDataArr, it's different from m_iFrameIndex.

 cocos2d::Vector _tweenList;
}

如何做到每幀更新骨頭的信息?

addChild(armature)后,Armaure中的onEnter(node進入舞臺就會調(diào)用,比如addchild),onEnter調(diào)scheduleUpdate調(diào)scheduleUpdateWithPriority調(diào)_scheduler->scheduleUpdate。這樣就每幀調(diào)用armature的update。

void Armature::update(float dt)
 {
 _animation->update(dt);
 for(const auto &bone : _topBoneList) {
 bone->update(dt);
 }
 _armatureTransformDirty = false;
 }

又調(diào)用了animation->update(dt);及遍歷調(diào)用bone->update(dt);animation->update(dt)如下:

void ArmatureAnimation::update(float dt)
 {
 ProcessBase::update(dt);
 
 for (const auto &tween : _tweenList)
 {
 tween->update(dt);
 }
 //省略一堆代碼
 }

又調(diào)用了tween->update(dt); 每一個update都會調(diào)用updateHandler(ProcessBase中update調(diào)用了update里調(diào)用updateHandler)

 void Tween::updateHandler()
 {
 //省略一堆代碼
 if (_loopType > ANIMATION_TO_LOOP_BACK)
 {
 percent = updateFrameData(percent);
 }
 
 if(_frameTweenEasing != ::cocosd::tweenfunc::TWEEN_EASING_MAX)
 {
 tweenNodeTo(percent);
 }
 }

tweenNodeTo調(diào)用了tweenNodeTo,其中的tweenData其實就是Bone的tweenData。根據(jù)percent計算了_tweenData的變化量。

 FrameData *Tween::tweenNodeTo(float percent, FrameData *node)
 {
 node = node == nullptr ? _tweenData : node;
 
 if (!_from->isTween)
 {
 percent = ;
 }
 
 node->x = _from->x + percent * _between->x;
 node->y = _from->y + percent * _between->y;
 node->scaleX = _from->scaleX + percent * _between->scaleX;
 node->scaleY = _from->scaleY + percent * _between->scaleY;
 node->skewX = _from->skewX + percent * _between->skewX;
 node->skewY = _from->skewY + percent * _between->skewY;
 
 _bone->setTransformDirty(true);
 
 if (node && _between->isUseColorInfo)
 {
 tweenColorTo(percent, node);
 }
 
 return node;
 }

轉(zhuǎn)了一大圈終于在每幀更新了Bone中的tweenData,最后看Bone的update,其根據(jù)tweenData計算了worldInfo、worldTransform。而且updateDisplay更新skin的信息,staticcast(display)->updateArmatureTransform();再transform = TransformConcat(_bone->getNodeToArmatureTransform(), _skinTransform);

 void Bone::update(float delta)
 {
 if (_parentBone)
 _boneTransformDirty = _boneTransformDirty || _parentBone->isTransformDirty();
 
 if (_armatureParentBone && !_boneTransformDirty)
 {
 _boneTransformDirty = _armatureParentBone->isTransformDirty();
 }
 
 if (_boneTransformDirty)
 {
 if (_dataVersion >= VERSION_COMBINED)
 {
 TransformHelp::nodeConcat(*_tweenData, *_boneData);
 _tweenData->scaleX -= ;
 _tweenData->scaleY -= ;
 }
 
 _worldInfo->copy(_tweenData);
 
 _worldInfo->x = _tweenData->x + _position.x;
 _worldInfo->y = _tweenData->y + _position.y;
 _worldInfo->scaleX = _tweenData->scaleX * _scaleX;
 _worldInfo->scaleY = _tweenData->scaleY * _scaleY;
 _worldInfo->skewX = _tweenData->skewX + _skewX + _rotationZ_X;
 _worldInfo->skewY = _tweenData->skewY + _skewY - _rotationZ_Y;
 
 if(_parentBone)
 {
 applyParentTransform(_parentBone);
 }
 else
 {
 if (_armatureParentBone)
 {
 applyParentTransform(_armatureParentBone);
 }
 }
 
 TransformHelp::nodeToMatrix(*_worldInfo, _worldTransform);
 
 if (_armatureParentBone)
 {
 _worldTransform = TransformConcat(_worldTransform, _armature->getNodeToParentTransform());
 }
 }
 
 DisplayFactory::updateDisplay(this, delta, _boneTransformDirty || _armature->getArmatureTransformDirty());
 
 for(const auto &obj: _children) {
 Bone *childBone = static_cast(obj);
 childBone->update(delta);
 }
 
 _boneTransformDirty = false;

如何展示(draw)出圖片(skin)

Armature詩歌node,加入父節(jié)點后會調(diào)用其draw函數(shù),遍歷draw了bone的顯示元素。

 void Armature::draw(cocosd::Renderer *renderer, const Mat &transform, uint_t flags)
 {
 if (_parentBone == nullptr && _batchNode == nullptr)
 {
 // CC_NODE_DRAW_SETUP();
 }
 
 
 for (auto& object : _children)
 {
 if (Bone *bone = dynamic_cast(object))
 {
 Node *node = bone->getDisplayRenderNode();
 
 if (nullptr == node)
 continue;
 
 switch (bone->getDisplayRenderNodeType())
 {
 case CS_DISPLAY_SPRITE:
 {
 Skin *skin = static_cast(node);
 skin->updateTransform();
 
 BlendFunc func = bone->getBlendFunc();
 
 if (func.src != _blendFunc.src || func.dst != _blendFunc.dst)
 {
 skin->setBlendFunc(bone->getBlendFunc());
 }
 else
 {
 skin->setBlendFunc(_blendFunc);
 }
 skin->draw(renderer, transform, flags);
 }
 break;
 case CS_DISPLAY_ARMATURE:
 {
 node->draw(renderer, transform, flags);
 }
 break;
 default:
 {
 node->visit(renderer, transform, flags);
 // CC_NODE_DRAW_SETUP();
 }
 break;
 }
 }
 else if(Node *node = dynamic_cast(object))
 {
 node->visit(renderer, transform, flags);
 // CC_NODE_DRAW_SETUP();
 }
 }
 }

再skin->draw(renderer, transform, flags);會用到剛剛更新的_quad,顯示出最新的圖片信息。

{
 Mat mv = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
 
 //TODO implement z order
 _quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, , mv);
 renderer->addCommand(&_quadCommand);
 }

至此,大家對cocos2dx里的骨骼動畫應(yīng)該有了全面的認(rèn)識,三篇文章介紹的比較粗糙,其實有些細(xì)節(jié)內(nèi)容我也沒看懂,不過不要在意這些細(xì)節(jié),沒有實際的改動需求的話,懂80%就可以了,細(xì)節(jié)可以需要的時候在仔細(xì)理解。

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

cocos2dx骨骼動畫Armature源碼剖析(三)_javascript技巧

cocos2dx骨骼動畫Armature源碼剖析(三)_javascript技巧:cocos2dx里骨骼動畫代碼在cocos -> editor-support -> cocostudio文件夾中,win下通過篩選器,文件結(jié)構(gòu)如下。(mac下沒有分,是整個一坨) armature(目錄): animation(目錄):動畫控制相關(guān)。 CCProcessBase(文件): ProcessBase
推薦度:
標(biāo)簽: 骨骼 cocos2dx cocos2d-x
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 欧美视频一区二区在线观看 | 亚洲精品乱码久久久久久v 亚洲精品免费观看 | 蜜臀91精品国产高清在线观看 | 国产高清在线免费观看 | 久久www免费人成_看片美女图 | 欧美日韩高清完整版在线观看免费 | 国产高清视频在线观看 | 国产高清精品一区 | 国产亚洲精品va在线 | 日本亚洲国产精品久久 | 久久综合中文字幕一区二区 | 亚洲视频在线观 | 亚洲国产精品免费观看 | 夜夜操夜夜骑 | 在线观看视频一区 | 一级毛片免费视频观看 | 在线精品欧美日韩 | 欧美日韩高清完整版在线观看免费 | 亚洲一区日韩二区欧美三区 | 国产99久久精品一区二区 | 高清在线一区二区 | 欧美 日韩 国产 成人 在线观看 | 一区二区视频在线观看高清视频在线 | 一区二区亚洲视频 | 在线日韩亚洲 | 五月天丁香网 | 亚洲一区二区三区91 | 在线 v亚洲 v欧美v 专区 | 久久国产综合精品欧美 | 日韩欧美网| 欧美 日韩 国产 在线 | 日韩手机视频 | 成人精品一区二区三区 | 97成人免费视频 | 欧美精品亚洲网站 | 国内精品视频免费观看 | 亚洲午夜电影 | 欧美精品一二三 | 欧美日韩在线第一页 | 国产精品久久久久久一区二区 | 激性欧美激情在线aa |