Does anyone have any idea why SetPosition for a sprite seems to be ignored in the Chipmonk physics engine collision callbacks, and how to change it’s position in the call backs?
I have a moving sprite.
When it is hit by a physics object (also a Sprite), I have callback listeners for onContactPreSolve, onContactBegin, and onContactSeparate. I can see Sprites colliding, and the callbacks get called.
However, in the callbacks I call SetPosition() for the sprite - but nothing happens, it keeps moving on its way with out going to the position. I have tried returning true and false from all the callbacks, just in case it made a difference.
I know the SetPosition() works in general, if I set it in my onMouseDown() callback it moves to the expected position when I click the mouse, and then continues on the vector of its travels (physic body’s velocity) just as expected.
I found a workaround, but it feels like a hack.
Instead of using SetPosition, I create a MoveTo action, with zero time.
This seems to do the job, but feels a bit cumbersome.
Example
auto action = cocos2d::MoveTo::create(0.0, cocos2d::Vec2(-Edge().getMinX(), 100));
_holes.at(0)->runAction(action);
Note interesting effect that IF SetPosition() is called using the MoveTo action also fails.
bool LairLichLordScene::onContactBegin(cocos2d::PhysicsContact& contact)
{
cc::log("onContactBegin A:%i B:%i", contact.getShapeA()->getCategoryBitmask(), contact.getShapeB()->getCategoryBitmask());
auto shapes = GetShapes(contact);
if (ShapesAre(shapes, (int)EObjectFlag::hole, (int)EObjectFlag::player)) {
PlayerFalling(true);
}
else if (ShapesAre(shapes, (int)EObjectFlag::edge, (int)EObjectFlag::hole)) {
auto hole = static_cast<cc::Sprite*>(shapes.second->getBody()->getNode());
auto pos = hole->getPosition();
pos.x = Edge().getMinX();
hole->setPosition(pos); // fails
auto action = cocos2d::MoveTo::create(0.0, cocos2d::Vec2(pos)); // works, UNLESS setPosition() was also called in which case it fails (?)
hole->runAction(action);
}
return true;
}
I think that you already know how to solve it. You can use setPosition() in contact callbacks for other sprites that are not involved with physics in that moment. Just call a function outside the callback and do it inside this function