using System; namespace Otter { /// /// Movement Component that can be used by an Entity to provide simple top-down style movement. /// This class requires an Axis component be assigned to it, and that Axis must be also updated /// by another source. A simple way to do this is to just have the Entity have an Axis component /// as well as the movement component, and then pass a reference to the axis into the movement. /// /// The movement also requires a Collider if you want it to be able to collide with walls and other /// things! /// public class BasicMovement : Movement { #region Public Fields /// /// The Speed of the Movement. /// public Speed Speed; /// /// The movement will accelerate toward this Speed. /// public Speed TargetSpeed; /// /// The rate at which the Speed will approach the TargetSpeed. /// public float Accel; /// /// Determines if diagonal movement should be limited. This is to fix the problem where a vector of /// (1, 1) would have more length than a vector of (1, 0) or (0, 1). /// public bool CircleClamp = true; /// /// The axis used to move. This must be set to something and updated for the movement to work. /// public Axis Axis; /// /// If true the movement will not update. /// public bool Freeze; #endregion #region Constructors /// /// Creates the basic movement. /// /// The maximum speed allowed in the x axis. /// The maximum speed allowed in the y axis. /// The acceleration. public BasicMovement(float xMax, float yMax, float accel) : base() { Speed = new Speed(xMax, yMax); TargetSpeed = new Speed(xMax, yMax); Accel = accel; } #endregion #region Public Methods /// /// Updates the Movement. /// public override void Update() { base.Update(); if (Freeze) return; TargetSpeed.MaxX = Speed.MaxX; TargetSpeed.MaxY = Speed.MaxY; if (Axis != null) { TargetSpeed.X = Axis.X * TargetSpeed.MaxX; TargetSpeed.Y = Axis.Y * TargetSpeed.MaxY; // Multiply by 1/sqrt(2) for circle clamp. if (CircleClamp && Math.Abs(TargetSpeed.X) == 1 && Math.Abs(TargetSpeed.Y) == 1) { TargetSpeed.X *= .7071f; TargetSpeed.Y *= .7071f; } } Speed.X = Util.Approach(Speed.X, TargetSpeed.X, Accel); Speed.Y = Util.Approach(Speed.Y, TargetSpeed.Y, Accel); MoveXY((int)Speed.X, (int)Speed.Y, Collider); if (OnMove != null) { OnMove(); } } /// /// A callback for when the horizontal sweep test hits a collision. /// /// public override void MoveCollideX(Collider collider) { Speed.X = 0; } /// /// A callback for when the vertical sweep test hits a collision. /// /// public override void MoveCollideY(Collider collider) { Speed.Y = 0; } #endregion } }