• Editor
  • AnimationState and cocos2d/cocos2d-x enhancements

Related Discussions
...

AnimationState can now queue animations to be switched to later via a new function, addAnimation. This takes a delay, which is the time from the start of the previous animation queued (or current animation if none are queued).

CCSkeleton for both cocos2d and cocos2d-x has been split into CCSkeleton and CCSkeletonAnimation. CCSkeleton just draws the skeleton and can be subclassed more easily to apply your own animations. CCSkeletonAnimation extends it and provides a simple API for applying one or more animations and queuing animations to be played later. Eg, to apply two AnimationStates in cocos2d:

animationNode = [CCSkeletonAnimation ...];
// By default the CCSkeletonAnimation has one animation state with index 0.
// Having one state is very common so methods that don't take a stateIndex use index 0.
[animationNode setAnimation:@"walk" loop:NO];
// Delay of 0 will play it after the previous one, any mix duration
// is taken into consideration.
[animationNode addAnimation:@"jump" loop:NO afterDelay:0];
[animationNode addAnimation:@"walk" loop:YES afterDelay:0];
// This adds a second animation state with index 1.
[animationNode addAnimationState];
// Note that index 1 is specified.
[animationNode setAnimation:@"wings" loop:YES forState:1];

There are no callbacks at this point. If callbacks are invoked when an animation is complete, users will have to track when animation has completed. Eg, they might want an animation to loop twice, then do something. Or they might want to play 3 animations, then do something.

I think it might be more flexible to have callbacks be based on time. CCSkeletonAnimation could have a list of callbacks, each of which has a time and block. When the time has elapsed, the block is executed. Eg:

[animationNode addCallback:some afterDelay:1.4f];

Once we have this, we can add methods like:

[animationNode addAnimation:@"jump" loop:NO afterDelay:0 forState:1 callback:something];

Internally that would compute the time when the added animation is complete and add the callback using that time. However, this doesn't make sense for animations that loop, since the callback would only be scheduled to execute once. The solution I guess would be to schedule the callback from when you want it to happen:

[animationNode addCallback:some afterDelay:someAnimation->duration * 3];

If you want it to happen on every loop, you could reschedule it inside the callback.

What do you guys think?

Right now I really need to move on to getting the other runtimes done so I can start getting editor features done. If I spend too much time along the way, things will never get finished. I don't want to sacrifice the quality of the work I do, but at the same time I need to prioritize a massive workload. Where possible I will need to punt non-essential features down the road. In the meantime, if someone wants to contribute via github, I will find time to evaluate and merge contributions.

Hi Nate,

This all sounds cool to me..

I updated to use this latest code in cocos2d-x, but I'm getting a weird compiler error:

.../CCSkeleton.h:63:19: Extra qualification on member 'setSkeletonData'

Any ideas?
thanks.

Oops, fixed!

Cool, works now,
Thanks!

Hi Nate,

I'm working with Sheila trying to figure out how to use your product in our game. I'm using Cococ2d-iphone and have downloaded the runtime and the sample and got all that to work.

All we are trying to do right now is test the features of the runtime and learn how to use the editor to create the animations we want to create. However, even after looking at the source and trying to do as much searching as I can I'm stuck and I think it might be a problem with how we are organizing our files or how we are using this new addAnimation feature.

Basically all I want to do right now is chain three animations together named "1 Hand Weapon", "Idle", "2 Hand Weapon". I can play each animation individually and it works fine. However, once I try to chain them the order of the chain will make one or more of the animations not play correctly.

There are also 3 skins in the mix a "default", "Clown", and "Nurse" skin. The "default" skin contains all the shared skin elements (like the Shotgun, facial features, and Pistol) where the Clown and Nurse skin have the art elements for those characters. Here is the code I'm using to play these three animations:

	animationNode = [CCSkeletonAnimation skeletonWithFile:@"skeleton.json" atlasFile:@"SpineHumanTest.txt" scale:1];
    Skin* myskin = SkeletonData_findSkin(animationNode.skeleton->data, "Clown");
    Skeleton_setSkin(animationNode.skeleton, myskin);
    Skeleton_setToBindPose(animationNode.skeleton);
    [animationNode setMixFrom:@"1 Hand Weapon" to:@"Idle" duration:0.2f];
    [animationNode setMixFrom:@"Idle" to:@"2 Hand Weapon" duration:0.2f];
	[animationNode setAnimation:@"1 Hand Weapon" loop:NO];
    [animationNode addAnimation:@"Idle" loop:NO afterDelay:0];
    [animationNode addAnimation:@"2 Hand Weapon" loop:YES afterDelay:0];

When they are in this order the final animation is missing the shotgun. If I change the order different elements will be missing, sometimes its the weapons, sometimes its different arms and hands we use for holding the weapons.

Is there something obvious I need to do to ensure this works?

Note you could call Skin_setSkinByName("Clown"). It looks like what you are doing is right. Can you email the assets so I can see the problem? contact@esotericsoftware.com

Got it and replied.

Note I just committed convenience methods for CCSkeleton, eg setSkin, setToBindPose.

Thanks the keying of the slot at the start of the animation fixed the problems. Thank you Nate!

Thank you for the convenience methods!