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

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

最新文章專題視頻專題問答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的某個節點??聪?/p>

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
主站蜘蛛池模板: 久久久久国产成人精品亚洲午夜 | 久久国产精品免费一区二区三区 | 另类专区欧美 | 亚洲乱码一二三四区麻豆 | 韩国精品在线 | 久久精品国产999久久久 | 999成人国产精品 | 欧美色图第一页 | 日韩第3页 | 成人久久久精品乱码一区二区三区 | 国产成人精品.一二区 | 久久久久久91香蕉国产 | 韩国精品一区二区久久 | 久久久网久久久久合久久久久 | 亲子乱子xxxxxx | 亚洲欧美h | 欧美在线视频在线观看 | 一区二区三区四区亚洲 | 国产欧美日韩精品综合 | 一区二区三区观看 | 日韩在线看片 | 欧美精品在线一区 | 欧美一级在线 | 亚洲欧洲国产成人综合一本 | 女同互忝互慰dv毛片观看 | 国产视频一区二区三区四区 | 欧美十区 | 免费一看一级毛片人 | 精品久久久久久久中文字幕 | 久久综合中文字幕一区二区 | 成人a毛片免费视频观看 | 台湾一级毛片永久免费 | 亚洲欧美日韩精品久久久 | 国产视频一区二区在线观看 | 一级成人毛片免费观看 | 亚洲日韩第一页 | 国产成人高清一区二区私人 | 国产一区二区三区欧美 | 亚洲国产精品免费观看 | 亚洲精品国产精品国自产观看 | 国产精品视频免费看 |