计算正确的脉冲或力以将Box2D体移动到特定位置 - Box2D

时间:2014-07-01 18:23:32

标签: ios iphone math box2d physics

我有一个关于将Box2D机身移动到特定位置的问题,而不使用它。

body->SetTransform(targetVector,body->GetAngle())

我有一些适用于applyForce(here)的代码:

const float destinationControl = 0.3f;
b2Vec2 missilePosition = _physicalBody->GetPosition();
b2Vec2 diff = targetPosition - missilePosition;
float dist = diff.Length();

if (dist > 0)
{

// compute the aiming direction
b2Vec2 direction = b2Vec2(diff.x / dist, diff.y / dist);

// get the current missile velocity because we will apply a force to compensate this.
b2Vec2 currentVelocity = _physicalBody->GetLinearVelocity();

// the missile ideal velocity is the direction to the target multiplied by the max speed
b2Vec2 desireVelocity = b2Vec2(direction.x * maxSpeed, direction.y * maxSpeed);

// compensate the current missile velocity by the desired velocity, based on the control factor

b2Vec2 finalVelocity = control * (desireVelocity - currentVelocity);

// transform our velocity into an impulse (get rid of the time and mass factor)
float temp = (_physicalBody->GetMass() / normalDelta);

b2Vec2 finalForce = b2Vec2(finalVelocity.x * temp, finalVelocity.y * temp);

_physicalBody->ApplyForce(finalForce, _physicalBody->GetWorldCenter());

}

但是当maxSpeed达到高位时,身体会快速移动到该位置。

所以有人知道如何计算力(ApplyForce)或冲动(ApplyLinearImpulse)以在特定时间内将身体移动到目标位置(非常精确)。

或者上面代码的解决方案。我的意思是计算maxSpeed以将身体在特定时间内移动到目标位置。

在我的谷歌搜索中,我发现了iforce关于投影轨迹的有趣文章 (here)。也许这也有帮助吗?

提前谢谢

2 个答案:

答案 0 :(得分:3)

我认为你大部分都是正确的,但是你没有检查身体是否会在下一个时间步骤中超过目标。这对我有用:

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 );

答案 1 :(得分:0)

单次施加力可以通过给定距离移动(先前的答案表明您可以通过未来帧中的额外力量来纠正计算中的错误):

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);
}

已知限制:

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.