Collision Detection fails on scaling sprite

I have a frog trying to eat bugs on a scene. The tongue sprite object starts with a 0 x scale so that it is hidden behind the frog’s head. Upon touch the tongue then scales out to 100% x and what I want is that if it collides with a fly, the fly gets eaten. I can successfully get my collision event listener to detect the collision if there is no scaling happening but when the tongue is scaling up to make contact, it does not detect it. Is this a bug or do I need to implement it in a different way?

Event Listener in the Scene:

bool FrogScene::init(){
...
    auto contact_listener = EventListenerPhysicsContact::create();
    contact_listener->onContactBegin = CC_CALLBACK_1(::FrogScene::onContactBegin, this);
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(contact_listener, this);
    
}

bool FrogScene::onContactBegin(PhysicsContact &contact){
    auto node_a = contact.getShapeA()->getBody();
    auto node_b = contact.getShapeB()->getBody();
    std::cout << "CONTACT!";
    
    if ( (1 == node_a->getCollisionBitmask() && 2 == node_b->getCollisionBitmask() ) ||
        (2 == node_a->getCollisionBitmask() && 1 == node_b->getCollisionBitmask() )) {
        CCLOG("Collision");
    }
    
    return true;
}

Tongue Actions:

auto rot_tongue = RotateTo::create(0.1, CC_RADIANS_TO_DEGREES(-angle));
auto scale_out = ScaleTo::create(0.2, 1.0, 1.0);
auto scale_down = ScaleTo::create(0.2, 0, 1.0);
tongue->runAction(Sequence::create(rot_tongue, scale_out, scale_down, nullptr));

Physics bodies for both however the category and collision bit mask is switched for the bug:

PhysicsBody* pb = PhysicsBody::createBox(Size(this->tongue->getContentSize().width, this->tongue->getContentSize().height));
pb->setCategoryBitmask(0x02);
pb->setCollisionBitmask(0x01);
pb->setContactTestBitmask(0xFFFFFFFF);
pb->setDynamic(false);

Any help is greatly appreciated!

I think you have to update the shape size too.

Hey @dreifrankensoft ,

Thanks for the reply. Do you mean like do set size in a call back at some point during the sequence?

Update the shape info on a call back or anywhere before the physics world will be updated.

Not sure I follow. I print out the size before setting the body and its the width of my sprite which is 1595.

this->tongue = Sprite::createWithSpriteFrameName("tongue.png");
std::cout << this->tongue->getContentSize().width;
PhysicsBody* pb = PhysicsBody::createBox(Size(this->tongue->getContentSize().width, this->tongue->getContentSize().height));

I then set the scale:

this->tongue->setScale(0, 1.0);

I think your problem is here. Timing 0.2 Its very less.
Try to increase it or give delay between this two action.

Slowing it down to 1 second didn’t do anything different. If I remove scaling all together it works however that makes me lose the animation effect I am hoping to get.

Ohk, it should work because i used in many games.
But i normally used ScaleTo::create(time, scaleFactor); Not the one with different x & y parameter.
May be that function has bug?!! try once this.
is your debug draw ON? How is it showing debug rect?

I did this:

auto move_out = MoveTo::create(0.2, pt);
auto move_back = MoveTo::create(0.2, tongue->getPosition());
tongue->runAction(Sequence::create(rot_tongue, move_out, move_back, nullptr));

and I am getting collision with it. But looks funny with a tongue sticking out the back of the frog. How did you do it with Scale?

As i said before

Try this once.

@smitpatel88
Doing it like this still didn’t work:

auto scale_out = ScaleTo::create(1.0, 1.0);
auto scale_down = ScaleTo::create(1.0, 0); 

beginning to wonder if this is a bug or just not a feature in cocos2dx?

Did you turn on debug draw? is it scaling on that time?
You will find red rect on image.
It should work as per my experience.

1 Like

@smitpatel88
Thanks for you help on this by the way.

I’m trying this but not seeing anything:

scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

then something is wrong with your code.

I found out the issue:

auto scale_down = ScaleTo::create(1.0,0, 1.0);

When scaling down to 0 it appears to remove the physics body.

auto scale_down = ScaleTo::create(1.0,0.1, 1.0);

The physics body remains on this scaling down to 10% of the sprite width and therefore when scaling out it makes contact with the other object.

Thanks for trying to help me debug this. Is this a bug in the cocos2dx or is that the way its supposed to be?

Yes, we can consider as bug.
Create bug in github issue
here : https://github.com/cocos2d/cocos2d-x/issues

Thank you @smitpatel88