• Runtimes
  • touch detection - properly

  • Modifié

Hello All,

I am trying to make a button out of spine Skeleton animation in cocos2dx. Its a simple, flat animation, that repeats over and over again. Here what I am doing

spAtlas* _atlasIcon;
spAttachmentLoader* _attachmentLoaderIcon;
spSkeletonData* _skeletonDataIcon;
spAnimationStateData* _stateDataIcon;


_atlasIcon=spAtlas_createFromFile("icon.atlas", 0);
_attachmentLoaderIcon=(spAttachmentLoader*)Cocos2dAttachmentLoader_create(_atlasIcon);
spSkeletonJson* jsonIcon= spSkeletonJson_createWithLoader(_attachmentLoaderIcon);
jsonIcon->scale = 1.0f;
_skeletonDataIcon=spSkeletonJson_readSkeletonDataFile(jsonIcon, "icon.json");
spSkeletonJson_dispose(jsonIcon);
_stateDataIcon=spAnimationStateData_create(_skeletonDataIcon);

auto spinner= spine::SkeletonAnimation::createWithData(_skeletonDataIcon, false);
spinner->addAnimation(0, "animation", true);
spinner->setPosition(Vec2(visibleSize.width/2, visibleSize.height/2));
spinner->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
this->addChild(spinner, 100);

auto listenerSpinner = cocos2d::EventListenerTouchOneByOne::create();
listenerSpinner->setSwallowTouches(true);

listenerSpinner->onTouchBegan = [&, spinner](cocos2d::Touch* touch, cocos2d::Event* event)
{
  
     auto target = static_cast<spine::SkeletonAnimation*>(event->getCurrentTarget());
     Point locationInNode = target->convertToNodeSpace(touch->getLocation());
    
    auto s = target->getBoundingBox();
    Rect rect = Rect(0,0, s.size.width, s.size.height);
     if (rect.containsPoint(locationInNode))
    {
        log("spinner began... x = %f, y = %f", locationInNode.x, locationInNode.y);
        // do something here
        return true;  // consume touch for button
    }
    
    return false;
    
    
};

listenerSpinner->onTouchEnded = [=](cocos2d::Touch* touch, cocos2d::Event* event)
{
    log("spinner touch ended");
};

_eventDispatcher->addEventListenerWithSceneGraphPriority(listenerSpinner, spinner);

the issue with this code is that it only consume touch at top right corner of the skeleton animation and not on the center and other corners. I cant understand what could be the issue, its has something to do with world transform or something but I just cant figure out what it is, having tried every thing. We still need to test bounding box made from the editor. I have also tested it by getting the spRegionAttachment* of the main image, but result are same. Please help/guide us to get the correct touch position.

thanks


Hello ALL,

So I was able to fix this problem/issue by using bounding box made in editor on skeleton.
here is the touch detection code. Enjoy!

spinner= spine::SkeletonAnimation::createWithData(_skeletonDataIcon, false);
spinner->addAnimation(0, "animation", true);
spinner->setPosition(Vec2(visibleSize.width/2, visibleSize.height /2));
spinner->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
this->addChild(spinner, 100);

auto spinnerBound = spSkeletonBounds_create();

auto listenerSpinner = cocos2d::EventListenerTouchOneByOne::create();
listenerSpinner->setSwallowTouches(true);

listenerSpinner->onTouchBegan = [&, spinnerBound](cocos2d::Touch* touch, cocos2d::Event* event)
{
   
    spSkeletonBounds_update(spinnerBound, spinner->getSkeleton(), true);
    auto target = event->getCurrentTarget();
    Vec2 locationInNode = target->convertToNodeSpace(touch->getLocation());
    if (spSkeletonBounds_containsPoint(spinnerBound, locationInNode.x, locationInNode.y))
    {
      return true; // consume touch
    }
    
    return false;
    
    
};

listenerSpinner->onTouchEnded = [&, spinnerBound](cocos2d::Touch* touch, cocos2d::Event* event)
{
    log("spinner touch ended");
    
    spSkeletonBounds_update(spinnerBound, spinner->getSkeleton(), true);
    auto target = event->getCurrentTarget();
    Vec2 locationInNode = target->convertToNodeSpace(touch->getLocation());
    if (spSkeletonBounds_containsPoint(spinnerBound, locationInNode.x, locationInNode.y))
    {
        log("spinner began... x = %f, y = %f", locationInNode.x, locationInNode.y);

    // do some thing
   }

};

_eventDispatcher->addEventListenerWithSceneGraphPriority(listenerSpinner, spinner);