AnimationBlender.h class AnimationBlender { public: enum BlendingTransition //不同的混合方式 { BlendSwitch, // 直接切换到目标动画 BlendWhileAnimating, // 交叉淡入淡出(源动画比例缩小,同时目标动画比例增大) BlendThenAnimate // 淡出源动画到目标动画第一帧,然后开始目标动画 }; private: Entity *mEntity; AnimationState *mSource; AnimationState *mTarget; BlendingTransition mTransition; bool loop; //是否循环 ~AnimationBlender() {} public: Real mTimeleft, mDuration; //持续时间 bool complete; void blend( const String &animation, BlendingTransition transition, Real duration, bool l ); void addTime( Real ); Real getProgress() { return mTimeleft/ mDuration; } AnimationState *getSource() { return mSource; } AnimationState *getTarget() { return mTarget; } AnimationBlender( Entity *); void init( const String &animation ); }; AnimationBlender.cpp void AnimationBlender::init(const String &animation) { //初始化所有动作的AnimationState AnimationStateSet *set = mEntity->getAllAnimationStates(); AnimationStateIterator it = set->getAnimationStateIterator(); while(it.hasMoreElements()) { AnimationState *anim = it.getNext(); anim->setEnabled(false); anim->setWeight(0); anim->setTimePosition(0); } //初始化mSource mSource = mEntity->getAnimationState( animation ); mSource->setEnabled(true); mSource->setWeight(1); mTimeleft = 0; mDuration = 1; mTarget = 0; complete=false; } void AnimationBlender::blend( const String &animation, BlendingTransition transition, Real duration, bool l ) { loop=l; //设置是否需要循环 if( transition == AnimationBlender::BlendSwitch ) {//如果混合方式为直接切换,改变mSource 即可 if( mSource != 0 ) mSource->setEnabled(false); mSource = mEntity->getAnimationState( animation ); mSource->setEnabled(true); mSource->setWeight(1); mSource->setTimePosition(0); mTimeleft = 0; } else { //先取得新的动画状态 AnimationState *newTarget = mEntity->getAnimationState( animation ); if( mTimeleft > 0 ) //前一次的混合尚未结束 { if( newTarget == mTarget ) { // 新的目标就是正在混合中的目标,什么也不做 } else if( newTarget == mSource ) { // 新的目标是源动画,直接go back mSource = mTarget; mTarget = newTarget; mTimeleft = mDuration - mTimeleft; } else { // 现在newTarget是真的新的动画了 if( mTimeleft < mDuration * 0.5 ) //上一次的混合进度还未超过一半 { // 简单替换Target就行了 mTarget->setEnabled(false); mTarget->setWeight(0); } else //如果已经过半,旧的target成为新的source { mSource->setEnabled(false); mSource->setWeight(0); mSource = mTarget; } mTarget = newTarget; mTarget->setEnabled(true); mTarget->setWeight( 1.0 - mTimeleft / mDuration ); mTarget->setTimePosition(0); } } else //上次的混合已经结束,当前未处于混合状态中 { mTransition = transition; mTimeleft = mDuration = duration; mTarget = newTarget; mTarget->setEnabled(true); mTarget->setWeight(0); mTarget->setTimePosition(0); } } } void AnimationBlender::addTime( Real time ) { if( mSource != 0 ) //若无AnimationState则不进行操作 { if( mTimeleft > 0 ) //两个动画仍在混合过程中 { mTimeleft -= time; if( mTimeleft < 0 ) { // 混合完毕,切换到目标动画 mSource->setEnabled(false); mSource->setWeight(0); mSource = mTarget; mSource->setEnabled(true); mSource->setWeight(1); mTarget = 0; } else { // 仍然处于混合状态中,改变两个动画的权值 mSource->setWeight(mTimeleft / mDuration); mTarget->setWeight(1.0 - mTimeleft / mDuration); //在这种混合方式下,需要为目标动画增加时间 if(mTransition == AnimationBlender::BlendWhileAnimating) mTarget->addTime(time); } } if (mSource->getTimePosition() >= mSource->getLength()) { complete=true; } else { complete=false; } mSource->addTime(time); mSource->setLoop(loop); } } AnimationBlender::AnimationBlender( Entity *entity ) : mEntity(entity){}