using System; using System.Collections.Generic; using FarseerPhysics.Dynamics; namespace FarseerPhysics.Controllers { /// /// Put a limit on the linear (translation - the movespeed) and angular (rotation) velocity /// of bodies added to this controller. /// public class VelocityLimitController : Controller { public bool LimitAngularVelocity = true; public bool LimitLinearVelocity = true; private List _bodies = new List(); private float _maxAngularSqared; private float _maxAngularVelocity; private float _maxLinearSqared; private float _maxLinearVelocity; /// /// Initializes a new instance of the class. /// Sets the max linear velocity to Settings.MaxTranslation /// Sets the max angular velocity to Settings.MaxRotation /// public VelocityLimitController() : base(ControllerType.VelocityLimitController) { MaxLinearVelocity = Settings.MaxTranslation; MaxAngularVelocity = Settings.MaxRotation; } /// /// Initializes a new instance of the class. /// Pass in 0 or float.MaxValue to disable the limit. /// maxAngularVelocity = 0 will disable the angular velocity limit. /// /// The max linear velocity. /// The max angular velocity. public VelocityLimitController(float maxLinearVelocity, float maxAngularVelocity) : base(ControllerType.VelocityLimitController) { if (maxLinearVelocity == 0 || maxLinearVelocity == float.MaxValue) LimitLinearVelocity = false; if (maxAngularVelocity == 0 || maxAngularVelocity == float.MaxValue) LimitAngularVelocity = false; MaxLinearVelocity = maxLinearVelocity; MaxAngularVelocity = maxAngularVelocity; } /// /// Gets or sets the max angular velocity. /// /// The max angular velocity. public float MaxAngularVelocity { get { return _maxAngularVelocity; } set { _maxAngularVelocity = value; _maxAngularSqared = _maxAngularVelocity * _maxAngularVelocity; } } /// /// Gets or sets the max linear velocity. /// /// The max linear velocity. public float MaxLinearVelocity { get { return _maxLinearVelocity; } set { _maxLinearVelocity = value; _maxLinearSqared = _maxLinearVelocity * _maxLinearVelocity; } } public override void Update(float dt) { foreach (Body body in _bodies) { if (!IsActiveOn(body)) continue; if (LimitLinearVelocity) { //Translation // Check for large velocities. float translationX = dt * body.LinearVelocityInternal.X; float translationY = dt * body.LinearVelocityInternal.Y; float result = translationX * translationX + translationY * translationY; if (result > dt * _maxLinearSqared) { float sq = (float)Math.Sqrt(result); float ratio = _maxLinearVelocity / sq; body.LinearVelocityInternal.X *= ratio; body.LinearVelocityInternal.Y *= ratio; } } if (LimitAngularVelocity) { //Rotation float rotation = dt * body.AngularVelocityInternal; if (rotation * rotation > _maxAngularSqared) { float ratio = _maxAngularVelocity / Math.Abs(rotation); body.AngularVelocityInternal *= ratio; } } } } public void AddBody(Body body) { _bodies.Add(body); } public void RemoveBody(Body body) { _bodies.Remove(body); } } }