3

I'm using Box2D through Libgdx to create a scene. I have a scenario where I would like to constantly propel a specific object using applyForce (the direction would change from time to time), but only up to a given speed.

Picture a circular object propelled by a rocket motor (with nozzles on all sides), in zero G, for illustration.

Is there a way to do this without recalculating the force applied, or performing a repeated calculation each update? I only know how to set a maximum speed for all objects. My best bet at the moment is to use linearDamping somehow, but I'm hoping there's a simpler solution.

mikołak
  • 9,605
  • 1
  • 48
  • 70

1 Answers1

11

You could override the current velocity with SetLinearVelocity.

b2Vec2 vel = body->GetLinearVelocity();
float speed = vel.Normalize();//normalizes vector and returns length
if ( speed > maxSpeed ) 
    body->SetLinearVelocity( maxSpeed * vel );

===============

EDIT: Simple air resistance can be modeled by applying a small drag force in the opposite direction of travel, scaled with the speed of travel.

b2Vec2 vel = body->GetLinearVelocity();
body->ApplyForce( 0.05 * -vel, body->GetWorldCenter() );

The scale value for the drag (0.05 in this example) determines the speed at which the drag force will equal the force applied by the rocket motor and the two forces cancel each other, giving a top speed.

maxSpeed = thrustForce.Length() / 0.05;

Purists will point out that drag is actually relative to the square of the velocity, so to be more accurate you could do:

b2Vec2 vel = body->GetLinearVelocity();
float speed = vel.Normalize(); //normalizes vector and returns length
body->ApplyForce( 0.05 * speed * speed * -vel, body->GetWorldCenter() );

... which I think would give you a top speed of

maxSpeed = sqrtf( thrustForce.Length() / 0.05 );
iforce2d
  • 8,194
  • 3
  • 29
  • 40
  • This would probably work, but is in my mind even less desirable, since it introduces an additional calculation to be done each update. Also, shouldn't calls to methods like `setVelocity` be avoided for dynamic bodies? – mikołak Sep 20 '12 at 18:03
  • It will definitely work because this is the same way that Box2d enforces the maximum speed limit that you mentioned in your question. Perhaps these calculations are not as much of a problem as you think... Yes, setting velocity directly is usually not recommended if you want realistic physics but that's not what you are doing here. – iforce2d Sep 20 '12 at 22:26
  • Regarding realism, well, I **am** trying to model air resistance ;)... But you may be right, I might be overthinking this. I'll check this solution. – mikołak Sep 21 '12 at 23:19
  • I see I forgot to add a follow-up. Unfortunately this solution is not suitable for me, since I want the objects to preserve their inertia, and using this answer will force me to recalculate it manually. – mikołak Jan 05 '13 at 21:28
  • I see, so you don't want a sudden hard limit on the speed. I added some ideas about air resistance. – iforce2d Jan 06 '13 at 08:08