editor-support -> cocostudio文件夾中,win下通過篩選器,文件結構如下。(mac下沒有分,是整個一坨) armature(目錄): animation(目錄):動畫控制相關。 CCProcessBase(文件): ProcessBase" />
  • <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題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關鍵字專題關鍵字專題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
    當前位置: 首頁 - 科技 - 知識百科 - 正文

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

    來源:懂視網 責編:小采 時間:2020-11-27 21:43:26
    文檔

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

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

    數據相關源碼

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

    再來看下數據相關的UML,總體來說,就是ArmatureDataManager依賴DataReaderHelper把flash導出的xml文件解析成程序直接用的XXData,XXData對應于xml的某個節點,比如FrameData就對應于節點()。

    BaseData

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

    作為FrameData和BoneData的基類,提供骨骼的狀態信息。從下文可知BoneData對應xml中的>中的b節點,FrameData對應xml中的節點,BoneData和FrameData都有

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

    BoneData

    BoneData對應xml中的>中的b節點

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

    FrameData

    FrameData對應xml中的節點,就是flash里的關鍵幀信息。

    DisplayData

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

    ArmatureData

    ArmatureData是對應節點,里面有這個骨骼的所有骨頭,可以看成骨骼動畫的骨骼。

    AnimationData

    AnimationData對應節點,里面有多個MovementData,MovementData(下面介紹)對應xml中的mov,為flash中的一個帶幀標簽的動畫。

    MovementData

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

    MovementBoneData

    MovementBoneData對應xml中>的b,里面有frameList,即為關鍵幀信息。

    小總結

    xml中的各個節點和XXData的對應關系如下表,xml各個字段的意義可以參考上篇文章

    再來看產生動畫相關的代碼

    ArmatureDataManager

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

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

     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是怎么產生的呢?當執行


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

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

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

    addDataFromFile這個代碼:

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

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

    Armature

    在載入了xml數據后,調用

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

    Armature部分代碼如下,ArmatureAnimation控制xml的mov節點,Bone中有Tween,這個Tween對應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為當前Bone的狀態,每幀都會更新這個值,并用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進入舞臺就會調用,比如addchild),onEnter調scheduleUpdate調scheduleUpdateWithPriority調_scheduler->scheduleUpdate。這樣就每幀調用armature的update。

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

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

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

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

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

    tweenNodeTo調用了tweenNodeTo,其中的tweenData其實就是Bone的tweenData。根據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;
     }
    

    轉了一大圈終于在每幀更新了Bone中的tweenData,最后看Bone的update,其根據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,加入父節點后會調用其draw函數,遍歷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里的骨骼動畫應該有了全面的認識,三篇文章介紹的比較粗糙,其實有些細節內容我也沒看懂,不過不要在意這些細節,沒有實際的改動需求的話,懂80%就可以了,細節可以需要的時候在仔細理解。

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

    文檔

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

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

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 欧洲成人午夜精品无码区久久| 国产精品91视频| 久久精品人人做人人爽97 | 精品一区二区三区在线视频| 四虎永久在线精品免费一区二区| 亚洲精品福利视频| 2021精品国产综合久久| 日产精品久久久久久久性色| 欧洲精品一区二区三区在线观看| 国产精品V亚洲精品V日韩精品| 精品一区二区久久久久久久网站| 国产精品无码a∨精品| 亚洲精品国产成人片| 亚洲精品乱码久久久久久不卡| 精品伦精品一区二区三区视频 | 国产精品99久久久久久人| 亚洲永久精品ww47| 久久久久亚洲精品男人的天堂| 国产精品欧美久久久久无广告| 久久精品这里热有精品| 国产成人精品亚洲日本在线| 国产精品无套内射迪丽热巴| 欧洲精品久久久av无码电影| 久久亚洲精品人成综合网| 无码人妻精品中文字幕| 一本色道久久综合亚洲精品| 亚洲国产成人乱码精品女人久久久不卡| 国产精品一区在线观看你懂的| 99久久99久久精品国产| 91精品日韩人妻无码久久不卡| 亚洲精品免费观看| 91精品国产91久久久久久蜜臀| 999久久久国产精品| 国产成人精品一区二区三区| 成人国产一区二区三区精品| 成人一区二区三区精品| 国产精品福利电影一区二区三区四区欧美白嫩精品 | 国语自产精品视频| 精品国产一区二区三区久久蜜臀 | 精品三级在线观看| 午夜精品视频在线|