Calculate correct impluse or force to move a Box2D body to a specific position - Box2D

北慕城南 提交于 2019-12-01 01:13:55

I think you have it mostly correct, but you are not checking to see if the body will overshoot the target in the next time step. Here is what works for me:

b2Vec2 targetPosition = ...;
float targetSpeed = ...;

b2Vec2 direction = targetPosition - body->GetPosition();
float distanceToTravel = direction.Normalize();

// For most of the movement, the target speed is ok
float speedToUse = targetSpeed;

// Check if this speed will cause overshoot in the next time step.
// If so, we need to scale the speed down to just enough to reach
// the target point. (Assuming here a step length based on 60 fps)
float distancePerTimestep = speedToUse / 60.0f;
if ( distancePerTimestep > distanceToTravel )
    speedToUse *= ( distanceToTravel / distancePerTimestep );

// The rest is pretty much what you had already:
b2Vec2 desiredVelocity = speedToUse * direction;
b2Vec2 changeInVelocity = desiredVelocity - body->GetLinearVelocity();

b2Vec2 force = body->GetMass() * 60.0f * changeInVelocity;
body->ApplyForce( force, body->GetWorldCenter(), true );

There is a way for single-time applied force to move by given distance (previous answer suggests that you can correct error in calculation by additional force in future frames):

public static void applyForceToMoveBy(float byX, float byY, Body body) {
    force.set(byX, byY);
    force.sub(body.getLinearVelocity());
    float mass = body.getMass();
    force.scl(mass * 30.45f);
    body.applyForceToCenter(force, true);
}

Known limitations:

1) LinearVelocity effect was not tested;
2) calculation was tested with body linear damping = 0.5f. Appreciate, if somebody know how to add it into formula;
3) magic number 30.45f - maybe this could be fixed by point 2 or by world frame delta.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!