Nobollel開発者ブログ

Nobollelのエンジニアが、UnityやCocos2d-xの旬な情報・技術を紹介します。

Spine Bounding Boxes (Cocos2d-x)

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.

f:id:nobollel:20170111201053p:plain

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.