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

<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答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
        主站蜘蛛池模板: 亚洲欧洲日产国产综合网| 国产青草视频免费观看97| 亚洲av无码专区在线观看素人| 亚洲国产精品xo在线观看| 在线看片免费人成视频福利| 亚洲福利在线播放| 国产一区二区三区亚洲综合| 成人超污免费网站在线看| 亚洲AV色吊丝无码| xxxxwww免费| 亚洲不卡视频在线观看| 精品无码国产污污污免费网站 | 色妞WWW精品免费视频| 亚洲系列中文字幕| 精品无码国产污污污免费网站 | 99久久久国产精品免费蜜臀| 亚洲午夜久久久影院伊人| 一个人免费播放在线视频看片| 亚洲精品无码激情AV| 无遮挡免费一区二区三区| 亚洲综合图色40p| 99久久成人国产精品免费| 亚洲av无码成h人动漫无遮挡 | 欧美a级成人网站免费| 亚洲另类古典武侠| 成年网站免费视频A在线双飞| 亚洲va精品中文字幕| 午夜色a大片在线观看免费| 另类专区另类专区亚洲| 久久精品亚洲男人的天堂| 91免费国产视频| 精品日韩亚洲AV无码一区二区三区 | 亚洲免费观看在线视频| 亚洲日韩中文字幕| 德国女人一级毛片免费| 国产亚洲日韩在线a不卡| 狠狠亚洲狠狠欧洲2019| 久久青草免费91观看| 2020久久精品亚洲热综合一本 | 亚洲色偷偷偷综合网| 免费a级毛片18以上观看精品|