欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

cocos2dx骨骼動(dòng)畫Armature源碼剖析(三)

 更新時(shí)間:2015年09月08日 10:01:55   作者:BigFengFeng  
本篇文章給大家分享cocos2dx骨骼動(dòng)畫Armature源碼剖析(三),代碼附有注釋,介紹的非常詳細(xì),需要的朋友可以參考下

cocos2dx里骨骼動(dòng)畫代碼在cocos -> editor-support -> cocostudio文件夾中,win下通過篩選器,文件結(jié)構(gòu)如下。(mac下沒有分,是整個(gè)一坨)

armature(目錄):

 animation(目錄):動(dòng)畫控制相關(guān)。
  CCProcessBase(文件):
   ProcessBase(類):CCTween和ArmatureAnimation的基類。
  CCTWeen(文件):
   Tween(類):控制flash里一個(gè)layer的動(dòng)畫。
  CCArmatureAnimation(文件):
   ArmatureAnimation(類):控制整個(gè)動(dòng)畫,內(nèi)有多個(gè)Tween。
 datas(目錄):xml或json轉(zhuǎn)成c++中直接用的數(shù)據(jù)結(jié)構(gòu)。
  CCDatas(文件):
   BaseData(類):BoneData、FrameData的基類,包含大小位置顏色等信息。
   DisplayData(類): SpriteDisplayData、ArmatureDisplayData、ParticleDisplayData的基類。
   SpriteDisplayData(類):骨骼中的顯示數(shù)據(jù)。
   ArmatureDisplayData(類):
   ParticleDisplayData(類):
   BoneData(類):單個(gè)骨骼數(shù)據(jù),flash中一個(gè)layer是一個(gè)骨骼。
   ArmatureData(類):骨骼數(shù)據(jù),整個(gè)骨骼結(jié)構(gòu)數(shù)據(jù)。
   FrameData(類):關(guān)鍵幀數(shù)據(jù)。
   MovementBoneData(類):帶有關(guān)鍵幀的骨骼數(shù)據(jù)。
   MovementData(類):一個(gè)完整動(dòng)畫數(shù)據(jù)。
   AnimationData(類):組動(dòng)畫數(shù)據(jù),包含多個(gè)MovementData。
   ContourData(類):
   TextureData(類):顯示圖片數(shù)據(jù)。
 utils(目錄):
  CCArmatureDataManager(文件):
   RelativeData(類):
   ArmatureDataManager(類):管理ArmatureData、AnimationData、TextureData。
  CCArmatureDefine(文件):
  CCDataReaderHelper(文件):
   _AsyncStruct(類):
   _DataInfo(類):
   DataReaderHelper(類):這正解析xml或json的類。
  CCSpriteFrameCacheHelper(文件):
   SpriteFrameCacheHelper(類):
  CCTransformHelp(文件):
   TransformHelp(類):矩陣運(yùn)算。
  CCUtilMath(文件):
 CCArmature(文件):
  Armature(類):控制整個(gè)骨骼動(dòng)畫,內(nèi)有ArmatureAnimation和ArmatureData。
 CCBone(文件):
  Bone(類):骨骼控制類
 display(目錄):顯示的圖片管理。
  CCBatchNode(文件):
   BatchNode(類):
  CCDecorativeDisplay(文件):
   DecorativeDisplay(類):
  CCDisplayFactory(文件):
   DisplayFactory(類):
  CCDisplayManager(文件):
   DisplayManager(類):
  CCSkin(文件):
   Skin(類):
 physics(目錄):物理引擎相關(guān),不分析。
  ColliderFilter(文件):
   ColliderFilter(類):
   ColliderBody(類):
   ColliderDetecotor(類)

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

從底層到高層分析一個(gè)類一個(gè)類分析

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

 

BaseData

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

BaseData.h

 class BaseData : public cocosd::Ref
 {
 public:
  //Calculate two BaseData's between value(to - from) and set to self
  virtual void subtract(BaseData *from, BaseData *to, bool limit);
 public:
  //位置,xml的x,y
  float x;     
  float y;  
  //xml中z   
  int zOrder; 
  //旋轉(zhuǎn),xml的kX,kY
  float skewX; 
  float skewY; 
  //縮放,xml的cX,cY
  float scaleX; 
  float scaleY; 
  //啥??
  float tweenRotate;  
  //顏色的變化屬性 
  bool isUseColorInfo; 
  int a, r, g, b;
 };

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

<x,y,kX,kY,cX,cY,pX,pY,z>等屬性,BaseDa代表了這些屬性。

BoneData

BoneData對(duì)應(yīng)xml中的<armature<b>>中的b節(jié)點(diǎn)

class BoneData : public BaseData
 {
 public:
  void addDisplayData(DisplayData *displayData);
  DisplayData *getDisplayData(int index);
 public:
  std::string name;   //! the bone's name
  std::string parentName;  //! the bone parent's name
  //! save DisplayData informations for the Bone
  cocosd::Vector<DisplayData*> displayDataList; 
  //仿射變換,程序里好像沒用這個(gè)屬性 
  cocosd::AffineTransform boneDataTransform;
 };

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

FrameData

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

 class FrameData : public BaseData
 {
 public:
  int frameID;
  //xml中dr,這一幀長度
  int duration;    
  //不知要他干啥
  bool isTween; 
  //xml中dI,顯示哪個(gè)圖    
  int displayIndex;
 };

DisplayData

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

ArmatureData

ArmatureData是對(duì)應(yīng)<armature>節(jié)點(diǎn),里面有這個(gè)骨骼的所有骨頭,可以看成骨骼動(dòng)畫的骨骼。

class ArmatureData : public cocosd::Ref
 {
 public:
  //添加骨骼信息
  void addBoneData(BoneData *boneData);
  BoneData *getBoneData(const std::string& boneName);
 public:
  std::string name;
  //多個(gè)骨頭信息
  cocosd::Map<std::string, BoneData*> boneDataDic;
  float dataVersion;
 };

AnimationData

AnimationData對(duì)應(yīng)<animation>節(jié)點(diǎn),里面有多個(gè)MovementData,MovementData(下面介紹)對(duì)應(yīng)xml中的mov,為flash中的一個(gè)帶幀標(biāo)簽的動(dòng)畫。

class AnimationData : public cocosd::Ref
 {
 public:
  void addMovement(MovementData *movData);
  MovementData *getMovement(const std::string& movementName);
  ssize_t getMovementCount();
 public:
  //<animation name="Dragon">中的name
  std::string name;
  //所有帶幀標(biāo)簽的動(dòng)畫map
  cocosd::Map<std::string, MovementData*> movementDataDic;
  //所有帶幀標(biāo)簽的動(dòng)畫名
  std::vector<std::string> movementNames;
 };

MovementData

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

 class MovementData : public cocosd::Ref
 {
 public:
  void addMovementBoneData(MovementBoneData *movBoneData);
  MovementBoneData *getMovementBoneData(const std::string& boneName);
 public:
  std::string name;
  //xml 中 dr
  int duration;
  //這怎么有個(gè)scale?? 
  float scale; 
  //xml中to  
  int durationTo;
  //xml中drTW
  int durationTween;
  //xml中l(wèi)p
  bool loop;
  //帶幀信息的骨骼  
  cocosd::Map<std::string, MovementBoneData*> movBoneDataDic;
 };

MovementBoneData

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

class MovementBoneData : public cocosd::Ref
 {
  void addFrameData(FrameData *frameData);
  FrameData *getFrameData(int index);
 public:
  //xml中的dl
  float delay;
  //xml中的sc    
  float scale;  
  //這個(gè)和MovementData中的duration是不是一個(gè)??  
  float duration;  
  std::string name; 
  //關(guān)鍵幀信息
  cocosd::Vector<FrameData*> frameList;
 };

小總結(jié)

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

 

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

 

ArmatureDataManager

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

ArmatureDataManager是個(gè)單例,用到動(dòng)畫時(shí)會(huì)到ArmatureDataManager取得要生成動(dòng)畫的數(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<std::string, ArmatureData*>&  getArmatureDatas() const;
  const cocosd::Map<std::string, AnimationData*>& getAnimationDatas() const;
  const cocosd::Map<std::string, TextureData*>&  getTextureDatas() const;
 protected:
  void addRelativeData(const std::string& configFilePath);
  RelativeData *getRelativeData(const std::string& configFilePath);
 private:
  cocosd::Map<std::string, ArmatureData*> _armarureDatas;
  cocosd::Map<std::string, AnimationData*> _animationDatas;
  cocosd::Map<std::string, TextureData*> _textureDatas;
  std::unordered_map<std::string, RelativeData> _relativeDatas;
 };

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

 ArmatureDataManager::getInstance()->addArmatureFileInfo(“dragon.xml”);

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

void ArmatureDataManager::addArmatureFileInfo(const std::string& configFilePath)
 {
  addRelativeData(configFilePath);
  _autoLoadSpriteFile = true;
  DataReaderHelper::getInstance()->addDataFromFile(configFilePath);
 }

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

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

addDataFromFile這個(gè)代碼:

void DataReaderHelper::addDataFromFile(const std::string& filePath)
 {
  //省略一些代碼
  
  DataInfo dataInfo;
  dataInfo.filename = filePathStr;
  dataInfo.asyncStruct = nullptr;
  dataInfo.baseFilePath = basefilePath;
  if (str == ".xml")
  {
   DataReaderHelper::addDataFromCache(contentStr, &dataInfo);
  }
  else if(str == ".json" || str == ".ExportJson")
  {
   DataReaderHelper::addDataFromJsonCache(contentStr, &dataInfo);
  }
  else if(isbinaryfilesrc)
  {
   DataReaderHelper::addDataFromBinaryCache(contentStr.c_str(),&dataInfo);
  }
 
  CC_SAFE_DELETE_ARRAY(pBytes);
 }

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

 void DataReaderHelper::addDataFromCache(const std::string& pFileContent, DataInfo *dataInfo)
 {
  tinyxml::XMLDocument document;
  document.Parse(pFileContent.c_str());
 
  tinyxml::XMLElement *root = document.RootElement();
  CCASSERT(root, "XML error or XML is empty.");
 
  root->QueryFloatAttribute(VERSION, &dataInfo->flashToolVersion);
 
 
  /*
  * Begin decode armature data from xml
  */
  tinyxml::XMLElement *armaturesXML = root->FirstChildElement(ARMATURES);
  tinyxml::XMLElement *armatureXML = armaturesXML->FirstChildElement(ARMATURE);
  while(armatureXML)
  {
   ArmatureData *armatureData = DataReaderHelper::decodeArmature(armatureXML, dataInfo);
 
   if (dataInfo->asyncStruct)
   {
    _dataReaderHelper->_addDataMutex.lock();
   }
   ArmatureDataManager::getInstance()->addArmatureData(armatureData->name.c_str(), armatureData, dataInfo->filename.c_str());
   armatureData->release();
   if (dataInfo->asyncStruct)
   {
    _dataReaderHelper->_addDataMutex.unlock();
   }
 
   armatureXML = armatureXML->NextSiblingElement(ARMATURE);
  }
 
 
  /*
  * Begin decode animation data from xml
  */
  tinyxml::XMLElement *animationsXML = root->FirstChildElement(ANIMATIONS);
  tinyxml::XMLElement *animationXML = animationsXML->FirstChildElement(ANIMATION);
  while(animationXML)
  {
   AnimationData *animationData = DataReaderHelper::decodeAnimation(animationXML, dataInfo);
   if (dataInfo->asyncStruct)
   {
    _dataReaderHelper->_addDataMutex.lock();
   }
   ArmatureDataManager::getInstance()->addAnimationData(animationData->name.c_str(), animationData, dataInfo->filename.c_str());
   animationData->release();
   if (dataInfo->asyncStruct)
   {
    _dataReaderHelper->_addDataMutex.unlock();
   }
   animationXML = animationXML->NextSiblingElement(ANIMATION);
  }
 
 
  /*
  * Begin decode texture data from xml
  */
  tinyxml::XMLElement *texturesXML = root->FirstChildElement(TEXTURE_ATLAS);
  tinyxml::XMLElement *textureXML = texturesXML->FirstChildElement(SUB_TEXTURE);
  while(textureXML)
  {
   TextureData *textureData = DataReaderHelper::decodeTexture(textureXML, dataInfo);
 
   if (dataInfo->asyncStruct)
   {
    _dataReaderHelper->_addDataMutex.lock();
   }
   ArmatureDataManager::getInstance()->addTextureData(textureData->name.c_str(), textureData, dataInfo->filename.c_str());
   textureData->release();
   if (dataInfo->asyncStruct)
   {
    _dataReaderHelper->_addDataMutex.unlock();
   }
   textureXML = textureXML->NextSiblingElement(SUB_TEXTURE);
  }
 }

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

Armature

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

  armature = Armature::create("Dragon");
  armature->getAnimation()->play("walk");
  armature->getAnimation()->setSpeedScale();
  armature->setPosition(VisibleRect::center().x, VisibleRect::center().y * .f);
  armature->setScale(.f);
  addChild(armature);

便展示了動(dòng)畫,那么這是如何做到的呢?

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

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

Bone

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

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

這個(gè)是每個(gè)骨頭的動(dòng)畫過程,見下面的movementBoneData。tweenData是Bone中tweenData的引用,在這每幀會(huì)計(jì)算這個(gè)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
  
  // 總共運(yùn)行了多少幀 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

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

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<Tween*> _tweenList;
}

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

addChild(armature)后,Armaure中的onEnter(node進(jìn)入舞臺(tái)就會(huì)調(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); 每一個(gè)update都會(huì)調(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其實(shí)就是Bone的tweenData。根據(jù)percent計(jì)算了_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計(jì)算了worldInfo、worldTransform。而且updateDisplay更新skin的信息,staticcast<skin*>(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<Bone*>(obj);
   childBone->update(delta);
  }
 
  _boneTransformDirty = false;

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

Armature詩歌node,加入父節(jié)點(diǎn)后會(huì)調(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<Bone *>(object))
   {
    Node *node = bone->getDisplayRenderNode();
 
    if (nullptr == node)
     continue;
 
    switch (bone->getDisplayRenderNodeType())
    {
    case CS_DISPLAY_SPRITE:
    {
     Skin *skin = static_cast<Skin *>(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<Node *>(object))
   {
    node->visit(renderer, transform, flags);
 //   CC_NODE_DRAW_SETUP();
   }
  }
 }

再skin->draw(renderer, transform, flags);會(huì)用到剛剛更新的_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);
 }

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

相關(guān)文章

最新評(píng)論