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