Last time i wrote a quick introduction on how to use Spine with Cocos2d-x, today i thought i would continue on the same path and show you how use Spine bounding boxes to achieve collision in Cocos2d-x.

The easiest way to get collision detecting for Spine models is to use the built in Bounding Box attachment. You could make one box covering your whole model, or make a more precise ones for each of your bones. Bounding boxes can also be switched on and off at any point in the timeline of your animations, for example in the middle of a sword swinging animation, or right as your hero draws his shield, for more exact collision timings.

Bounding boxes are created the same way as other attachments in Spine, select the bone you want to use as parent for your bounding box, press "New..." in the bottom right of the screen, and a dialog box will pop up asking you for a name. After naming your box, a plus sign will appear next to the cursor and we can now start putting down the bounds of our "box" by clicking. Once you are happy, complete the shape by clicking on the first node you put down. The shape of the bounding box can be edited at any time from the hierarchy.

After exporting, we can start using the bounding box in Cocos2d-x. For this example i will use the mouse position to see if we hit our target.

// First we create a skeletonBounds object
auto bounds = spSkeletonBounds_create();
// Listener to get out click position
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = [bounds](Touch* touch, Event* event) {
// We then need to update the bounds to get their current position
spSkeletonBounds_update(bounds, _skeletonNode->getSkeleton(), true);
// The location of the click
auto target = event->getCurrentTarget();
auto location = target->convertToNodeSpace(touch->getLocation());
// Then all we have to do is check if the click was within the bounds!
if (spSkeletonBounds_containsPoint(bounds, location.x, location.y)) {
// We hit something!
CCLOG("Hit!");
}
return true;
};

There is of course a lot more fancy stuff you can do, spSkeletonBounds_containsPoint returns the first object to get hit, which you could then use to detect which body part it was. Or if you already know what bounding box you are looking for, you can use spPolygon_containsPoint instead.

Spine is a 2d based animation software, what makes it stand out is its ability to use bones and meshes, just like any 3d animation tool, to effortlessly create awesome 2d animation for your games. Another great feature is being able to use "skins" and "attachment", allowing you to reuse the same skeleton and animations for while switching out things like clothing and weapons for your character.

Importing and rigging

Before starting to animate, we need to import some images. All we have to do is finding the Images tab in the hierarchy and press the Browse button at the bottom, then select the folder with the images we want to import. We can now use the images by simply dragging them onto our stage, and arranging them how we want our model to look.

If you already have your model assembled in Photoshop or Gimp, you can use the export script to generate a JSON file that can be imported directly into Spine.

To create bones for your character, press the "Create new bones" at the bottom left of the screen, hold ctrl and click on the image you want to attach the bone to, then click and drag from where you want the actual bone. Remember to always select the bone you want as parent before creating new bones.

Animations

To create a new animation, find the Animations tab in the hierarchy and then press the "New Animation" button at the bottom of the screen. Once you have given your new Animation a name, press SETUP at the top left to go into animation mode.

The basics of the Dropsheet is to create one or more keyframe at different positions in the timeline, and Spine will tween between the two, making a smooth transition. To create a keyframe, press anywhere in the timeline where you want the new frame to be, then either move or rotate the body part you want to animate, or manually put in the values in the transform window above the Dropsheet.

You can also put "Events" in the timeline that can be used for things like footstep effects or to let your game know the exact timing to spawn the bullet in your shooting animation. Creating an event is just like creating animations, find the Event tab and press New Event. To use the event in your animation, go to the frame you want the event to occur, and press the small key next to the event you want to use.

Runtimes and scripting

To get our animations working in our game we need one the Spine runtime. Today i will be using the Cocos2d-x runtime, but spine is supported by a wide range of popular engines and languages, you can find a full list here.
http://esotericsoftware.com/spine-runtimes

Getting the character to show up in Cocos2d-x is super easy, if you have Cocos2d-x installed, you should already have the runtime too, but we need to add the header file to our class. I will also use the Spine namespace for convenience.

HelloWorld.h

#include <spine/spine-cocos2dx.h>
using namespace spine;

And with that we can add our character to our game!

HelloWorld.ccp

// creates a node holding our character
auto skeletonNode = SkeletonAnimation::createWithFile("res/koko.json", "res/koko00.atlas", 1.0f);
// the position we want our character to appear
skeletonNode->setPosition(Vec2(600, 10));
// (optional) called once a new animation starts
skeletonNode->setStartListener([skeletonNode] (int trackIndex) {
spTrackEntry* entry = spAnimationState_getCurrent(skeletonNode->getState(), trackIndex);
CCLOG("start: %s", entry->animation->name);
});
// (optional) called every time an animation is completed
skeletonNode->setCompleteListener([skeletonNode] (int trackIndex, int loopCount) {
CCLOG("loop count: %d", loopCount);
});
// (optional) this is called each time the animation runs into the events we added in spine
skeletonNode->setEventListener([skeletonNode] (int trackIndex, spEvent* event) {
CCLOG("event: %s", event->data->name);
});
// the most basic way to play an animation is to use setAnimation(
// int trackIndex, const std::string &animationName, bool loop)
skeletonNode->setAnimation(0, "walk", true);
// finally we can add the node to the stage
addChild(skeletonNode);