Skip to content

Instantly share code, notes, and snippets.

@stevetranby
Last active May 13, 2016 07:55
Show Gist options
  • Save stevetranby/ce0bf403810ae6ba4aa213a59b45f8ef to your computer and use it in GitHub Desktop.
Save stevetranby/ce0bf403810ae6ba4aa213a59b45f8ef to your computer and use it in GitHub Desktop.
Animate multiple Sprite Nodes each with a separate Animation
#include "extensions/STActions.h"
USING_NS_CC;
////////////////////////////////////////////////////////////////////////
STAnimateInSync::STAnimateInSync() {}
STAnimateInSync::~STAnimateInSync() {
// TODO: release all animtargets
}
////////////////////////////////////////////////////////////////////////
STAnimateInSync* STAnimateInSync::create(Animation* pAnim, const std::vector<AnimationTargetPair>& animsTargetsToSync)
{
STAnimateInSync *ret = new STAnimateInSync();
if (ret && ret->initWithAnimation(pAnim, animsTargetsToSync))
{
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
bool STAnimateInSync::initWithAnimation(Animation* pAnim, const std::vector<AnimationTargetPair>& animsTargetsToSync)
{
if(! Animate::initWithAnimation(pAnim))
return false;
// stash the rest of the animations and target sprites
for (auto animTarget : animsTargetsToSync)
{
auto anim = animTarget.first;
auto target = animTarget.second;
anim->retain();
target->retain();
_animTargets.push_back(std::make_pair(anim, target));
}
return true;
}
////////////////////////////////////////////////////////////////////////
STAnimateInSync* STAnimateInSync::clone() const
{
STAnimateInSync *pCopy = new STAnimateInSync();
// TODO: just clone vector??
std::vector<AnimationTargetPair> animTargetPairs;
for(auto& animTarget : _animTargets) {
animTargetPairs.push_back(animTarget);
}
pCopy->initWithAnimation(getAnimation()->clone(), animTargetPairs);
return pCopy;
}
// MARK: -
void STAnimateInSync::update(float t)
{
Animation* _animation = getAnimation();
// if t==1, ignore. Animation should finish with t==1
if( t < 1.f ) {
t *= _animation->getLoops();
// new loop? If so, reset frame counter
unsigned int loopNumber = (unsigned int)t;
if( loopNumber > _executedLoops ) {
_nextFrame = 0;
_executedLoops++;
}
// new t for animations
t = fmodf(t, 1.f);
}
auto numberOfFrames = _animation->getFrames().size();
SpriteFrame *frameToDisplay = nullptr;
for(auto i = _nextFrame; i < numberOfFrames; i++ )
{
float splitTime = _splitTimes->at(size_t(i));
if( splitTime <= t )
{
auto frame = _animation->getFrames().at(i);
frameToDisplay = frame->getSpriteFrame();
(static_cast<Sprite*>(_target)->setSpriteFrame(frameToDisplay));
// sync targets 2+ (iterator i through Animations, iterator j through Sprite targets)
for (auto animTarget : _animTargets)
{
auto anim2 = animTarget.first;
auto target2 = animTarget.second;
if(i < anim2->getFrames().size()) {
auto frame2 = anim2->getFrames().at(i);
auto frameToDisplay2 = frame2->getSpriteFrame();
target2->setSpriteFrame(frameToDisplay2);
}
}
_nextFrame = i+1;
}
else
{
// Issue 1438. Could be more than one frame per tick, due to low frame rate or frame delta < 1/FPS
break;
}
}
}
Animate* STAnimateInSync::reverse() const
{
CCASSERT(false, "Not implemented!");
return nullptr;
// auto arr = getAnimation()->getFrames();
// arr.reverse();
// auto newAnim = Animation::create(arr,
// _animation->getDelayPerUnit(),
// _animation->getLoops());
// newAnim->setRestoreOriginalFrame(_animation->getRestoreOriginalFrame());
//
//
// // Sync Animation
// auto arrayToSync = _animationToSync->getFrames();
// arrayToSync.reverse();
// auto newAnimToSync = Animation::create(arrayToSync,
// _animationToSync->getDelayPerUnit(),
// _animationToSync->getLoops());
// newAnimToSync->setRestoreOriginalFrame(_animation->getRestoreOriginalFrame());
//
// // Sync Animation 2
// if(_animationToSync2 && _targetToSync2)
// {
// auto arrayToSync2 = _animationToSync2->getFrames();
// arrayToSync2.reverse();
// auto newAnimToSync2 = Animation::create(arrayToSync2,
// _animationToSync2->getDelayPerUnit(),
// _animationToSync2->getLoops());
// newAnimToSync2->setRestoreOriginalFrame(_animation->getRestoreOriginalFrame());
// return create(newAnim, newAnimToSync, _targetToSync, newAnimToSync2, _targetToSync2);
// }
// else
// {
// return create(newAnim, newAnimToSync, _targetToSync, nullptr, nullptr);
// }
}
typedef std::pair<cocos2d::Animation*, cocos2d::Sprite*> AnimationTargetPair;
class STAnimateInSync : public cocos2d::Animate
{
public:
STAnimateInSync();
virtual ~STAnimateInSync();
static STAnimateInSync* create(cocos2d::Animation* pAnim, const std::vector<AnimationTargetPair>& animsTargetsToSync);
bool initWithAnimation(cocos2d::Animation* pAnim, const std::vector<AnimationTargetPair>& animsTargetsToSync);
void update(float t) override;
STAnimateInSync* clone() const override;
cocos2d::Animate* reverse() const override;
private:
std::vector<AnimationTargetPair> _animTargets;
};
// container class might hold the layers
// Sprite* _spriteLayer1, *_spriteLayer2, *_spriteLayer3;
// animation to sprite map
std::vector<AnimationTargetPair> animTargets;
Animation* anim1 = // get animation from somewhere
animTargets.push_back(std::make_pair(anim1, _spriteLayer1));
Animation* anim2 = // get animation from somewhere
animTargets.push_back(std::make_pair(anim2, _spriteLayer2));
Animation* anim3 = // get animation from somewhere
animTargets.push_back(std::make_pair(anim3, _spriteLayer3));
// Run action on some Node* that exists as long as sprite layers
//auto animAction = Animate::create(animation);
auto animAction = STAnimateInSync::create(animation, animTargets);
auto action = RepeatForever::create(animAction);
// run on a container node holding the layers
this->runAction(action);
// or run on base layer
_spriteLayer1->runAction(action);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment