Loading Image
Loading Image
Loading Image
Loading Image
Loading Image
Hello All!
We're using Spine and the Spine cocos2d runtime to animate our main character Bobo the monkey in a new app called "Photo Bobo". It's a baby safe photo browser for iOS with some fun animations that sometimes have very tight interaction with photos (using facial recognition). This app for babies is all about showing interesting, randomly selected animations on top of a users' [family] photos.
I thought I would share some cocos2d snippets and techniques related to Spine in case they can be of help to anyone else. I'm trying to grab and summarize the useful snippets without dropping an overwhelming amount of unrelated code here, so let me know if you spot something amiss.
- On app startup, we scan available animation names and sort them into buckets of what contexts they can apply to. We use prefixes on animation names to describe what context(s) they are for and that gives us a simple way to filter what is available at runtime without an additional config file. Also this lets the animator add new animations with (usually) no code changes, and see them directly in the app. Of course this is most useful when your app allows for picking a random anim from a bucket sometimes.
In cocos2d:
node = [CCSkeletonAnimation skeletonWithFile:@"my.json" atlasFile:@"my.atlas" scale:.5];
for (int i = 0; i < node.skeleton->data->animationCount; ++i)
{
NSString animationName = @(node.skeleton->data->animations[i]->name);
// add to context bucket based on name prefix.
// set anchoring based on suffix (see #2)
}
- The app's main character, Bobo the monkey, is playing amongst your photos. Bobo generally makes a unique entrance and exit from a screen edge/corner specific to the animation. We suffixed animation names with an edge/corner abbreviation, representing an anchor point and then at runtime, we adjust the cocos2d 'node' to be anchored to that same place. This lets us design a single animation for all form factors of iPhone and iPad. In Spine, we design the animation so that the main axes in spine represent that corner/edge that the anim is anchored to.
In Spine: (animation_name is "basic_monkey_jump_tl". tl = top left)
y
|
|
x
---
+
---
| Monkey
|
In cocos2d:
node.position = ccp(0, screenheight); // top left
In Spine: (animation_name is "full_monkey_giggle_bc". bc = bottom center)
y
|
Monkey
x
---
+
---
|
|
In cocos2d:
node.position = ccp(screenwidth/2.0, 0);
We use spine events to mark the triggering of particle effects and programmatic animations. It's quite helpful to be able to retrieve the exact position of a bone that is the source of the effect/animation.
In Spine: We add a keyframe for an event named "throw_mustache" at the point in the timeline where the mustache should leave Bobo’s hand (to be tossed up onto the photo). In Spine, the mustache is taken out of the animation at that keyframe.
In cocos2d:
[node setDelegate:self]; // during init, subscribe for the spine event callback
...
- (void) animationDidTriggerEvent:(CCSkeletonAnimation*)animation track:(int)trackIndex event:(Event*)event {
NSString *eventName = @(event->data->name);
if([eventName isEqualToString:@"throw_mustache"])
[self triggerMustacheToss];
}
- (void) triggerMustacheToss {
Bone* leftHand = Skeleton_findBone(node.skeleton, "left hand");
CGPoint startingPoint = ccp(leftHand->worldX, leftHand->worldY);
startingPoint = [node convertToWorldSpace:startingPoint]; // exact cocos2d coordinates of the center of the left hand bone on screen.
// toss up a mustache starting from the starting point with a bezier curve to a
// destination point and rotation/scaling,etc... in the spine anim, the
// mustache is taken off at this frame, and it's up to our programmatic
// mustache animation (using cocos2d actions) to pickup where it left off
}
Hope something there is helpful to somebody! Happy animating!
Oh, here's the link to the app on the app store in case you know a baby/parent that would be interested: http://itunes.apple.com/app/id722364512?mt=8