2
\$\begingroup\$

I've created a bullet body and stored a reference to it in herobody:

bDef.type = b2_dynamicBody;
bDef.position.Set(herobody->GetPosition().x, herobody->GetPosition().y);
b = world->CreateBody(&bDef);
b2FixtureDef fixturebDef;
b2CircleShape circlebShape;
circlebShape.m_radius = 0.05;
fixturebDef.shape = &circlebShape;
b->CreateFixture(&fixturebDef);

I'm trying to change the current position of the bullet. I tried to use SetTransform but I get an error Assertion failed: (IsLocked() == false) during world->step in my update method.

// This doesn't work. Causes the above assertion.
/*
b->SetTransform(
  b2Vec2(
    herobody->GetPosition().x,
    herobody->GetPosition().y
  ),
  0
);
*/

// This works, but doesn't set position directly.
b->ApplyLinearImpulse(b2Vec2(5, 0), b->GetWorldCenter(),true);

How do I do this correctly?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Call SetTransform before or after your World::step call. Make sure it's not inside a Box2D callback, as those happen inside the step, during which the World is locked.


Further details:

The isLocked() == false assert implies you're attempting to directly change something in the Box2D World during a simulation step. This could break the simulation, so Box2D guards against it. SetTransform directly changes the body's position, so it is disallowed when locked.

ApplyLinearImpulse works even when locked, because all it does is register a new impulse that should act on the body, which does not directly change anything. The impulse is only applied on the next world step.


If you want the SetTransform to in response to some event (not every step), you'll need to introduce some additional state. For example, a bool shouldResetBallPosition that the appropriate callback sets to true. You can then then check for that inside your update method, with something like—

if (shouldResetBallPosition) {
    b->setTransform( ... );
    ...
    shouldResetBallPosition = false;
}
\$\endgroup\$
8
  • \$\begingroup\$ but when i called SetTransform before world::step in update. it update position every second and ApplyLinearImpulse can't work :/ \$\endgroup\$
    – dex3
    Commented Oct 12, 2015 at 18:49
  • \$\begingroup\$ @dex3 What do you mean by "ApplyLinearImpulse can't work"? \$\endgroup\$
    – Anko
    Commented Oct 12, 2015 at 18:51
  • \$\begingroup\$ hero throw ball (applylinearimpulse) and it immediately back to position from (transform) ;/ i would like to do sth like this: If i click button it back to position hero and next throw again \$\endgroup\$
    – dex3
    Commented Oct 12, 2015 at 18:58
  • \$\begingroup\$ @dex3 I think I see what you mean: you don't want the SetPosition to happen every step, but only in response to something else, like a mouse click. I edited to address that. Does it help? \$\endgroup\$
    – Anko
    Commented Oct 12, 2015 at 19:10
  • \$\begingroup\$ is it the only way to do that? or do you have some idea how to storage it and recall ? \$\endgroup\$
    – dex3
    Commented Oct 12, 2015 at 19:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .