0
\$\begingroup\$

I'm trying to develop a system where there are two types of velocity limits.

  1. The velocity that a rigid body can achieve on its own.
  2. The velocity cap which is reachable by interference with other forces.

(Bear in mind the physics aren't 100% realistic).

For example,

  • Hard limit is 1000.
  • Spaceship A can travel up to 300 pixels per second.
  • Spaceship B can travel up to 600 pixels per second.

So on its on spaceship A will only be able to go at 300, but if spaceship B were to tail gate and start ramming A, then A will go a bit faster.

In any case, regardless of the forces, nothing can go faster than the hard limit.

Now the hard limit is very easy to implement:

public override void _IntegrateForces(PhysicsDirectBodyState2D state)
{
    base._IntegrateForces(state);

    state.LinearVelocity = state.LinearVelocity.LimitLength(MaxLinearVelocity);
}

The part im having such trouble with, is capping the forces, for limit 1:

if (
    (LinearVelocity.X >=  MaxAppliedForceLinearVelocity && directionalForce.X > 0) ||
    (LinearVelocity.X <= -MaxAppliedForceLinearVelocity && directionalForce.X < 0)
) {
    directionalForce = new Vector2(0, directionalForce.Y);
}

if (
    (LinearVelocity.Y >=  MaxAppliedForceLinearVelocity && directionalForce.Y > 0) ||
    (LinearVelocity.Y <= -MaxAppliedForceLinearVelocity && directionalForce.Y < 0)
) {
    directionalForce = new Vector2(directionalForce.X, 0);
}

ApplyCentralForce(directionalForce.Rotated(Rotation));

Now something like just the above might work OK assuming that the ship is moving on only one axis, but the velocity could exceed it if moving along two axis. The problem is that the forces need to stop in one direction to allow gains in the other direction, and to autocorrect itself because forward movement may be more powerful than lateral movement.

The hard limit works, but individual ships and missiles, must not exceed their own limit unless something else impacts them. This is my problem. Thank you.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$
  1. Get current velocity
  2. Add new self_input
  3. Clamp the result to max(current, self_max) (current might be 450, self-max is 300, therefore, you are clamping to 450).
  4. Set the resulting velocity to the object
  5. Repeat 1-4, but replace self_input with extern_input and self_max with extern_max.

The only gotcha you don't see with your code is that you can do it twice. Once for global max (then apply input forces) and second time for the local max or current velocity, which ever is bigger.

Pseudocode version:

base._IntegrateForces(state);
state.LinearVelocity = state.LinearVelocity.LimitLength(MaxLinearVelocity);
applyInputForces();
MaxControlVelocity = Max(state.LinearVelocity,MaxAppliedForceLinearVelocity);
state.LinearVelocity = state.LinearVelocity.LimitLength(MaxControlVelocity);
\$\endgroup\$

You must log in to answer this question.

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