2 using System.Collections.Generic;
5 using Microsoft.Xna.Framework;
10 /// A class to manage the motion of objects on a grid of cells.
11 /// Each update you can pass a direction and the manager will move
12 /// the position to that point while also enforcing a speed limit.
13 /// This class does not detect collisions, so care must be taken
14 /// to only pass directions to a walkable cell during an update.
16 public class MovementManager
18 #region Public Properties
21 /// Get the current position in map coordinates. This is the
22 /// smooth, interpolated set of coordinates.
24 public Vector2 Position { get { return mPosition; } }
27 /// Get the grid coordinates where the object is at or
30 public Point Coordinates { get { return mCoordinates; } }
33 /// Get and set the speed of movement in grid cells / second.
40 #region Public Methods
43 /// Construct a movement manager with the initial position of
44 /// the thing you want to track.
46 /// <param name="position">Grid coordinates.</param>
47 public MovementManager(Point position)
49 mPosition = new Vector2((float)position.X, (float)position.Y);
50 mCoordinates = position;
51 mLastCoordinates = position;
56 /// Construct a movement manager with the initial position of
57 /// the thing you want to track and its speed.
59 /// <param name="position">Grid coordinates.</param>
60 /// <param name="speed">Speed: Grid cells per second.</param>
61 public MovementManager(Point position, float speed)
63 mPosition = new Vector2((float)position.X, (float)position.Y);
64 mCoordinates = position;
65 mLastCoordinates = position;
71 /// Update the movement manager with the timeslice and no directions.
73 /// <param name="timeSpan">The timeslice.</param>
74 public void Update(TimeSpan timeSpan)
76 Update(timeSpan, false, false, false, false);
80 /// Update the movement manager with the timeslice and the directions
81 /// the object is supposed to go. The directions will be ignored if the
82 /// object is currently in transit from one cell to another.
84 /// <param name="timeSpan">The timeslice.</param>
85 /// <param name="moveLeft">Want to move left.</param>
86 /// <param name="moveRight">Want to move right.</param>
87 /// <param name="moveUp">Want to move up.</param>
88 /// <param name="moveDown">Want to move down.</param>
89 public void Update(TimeSpan timeSpan, bool moveLeft, bool moveRight, bool moveUp, bool moveDown)
91 float passedTime = (float)timeSpan.TotalSeconds;
93 bool requestMove = (moveLeft ^ moveRight) || (moveUp ^ moveDown);
94 if (!mIsMoving && requestMove)
96 UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);
99 mTimeAccumulator = passedTime;
101 RecalculatePosition(mTimeAccumulator / mInverseSpeed);
105 mTimeAccumulator += passedTime;
107 float alpha = mTimeAccumulator / mInverseSpeed;
112 mTimeAccumulator = mTimeAccumulator - mInverseSpeed;
113 alpha = mTimeAccumulator / mInverseSpeed;
115 UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);
124 RecalculatePosition(alpha);
130 /// Helper method to get neighbor cells from a point and directions.
132 /// <param name="point">The point.</param>
133 /// <param name="left">To the left.</param>
134 /// <param name="right">To the right.</param>
135 /// <param name="up">Above.</param>
136 /// <param name="down">Below.</param>
137 /// <returns>The neighbor cell coordinates.</returns>
138 public static Point GetNeighborCell(Point point, bool left, bool right, bool up, bool down)
141 if (right) point.X++;
150 #region Private Methods
152 void RecalculatePosition(float alpha)
154 Console.WriteLine("last: " + mLastCoordinates + ", now: " + mCoordinates + ", alpha: " + alpha);
155 mPosition.X = (float)mLastCoordinates.X + alpha * ((float)mCoordinates.X - (float)mLastCoordinates.X);
156 mPosition.Y = (float)mLastCoordinates.Y + alpha * ((float)mCoordinates.Y - (float)mLastCoordinates.Y);
159 void UpdateCoordinates(bool moveLeft, bool moveRight, bool moveUp, bool moveDown)
161 mLastCoordinates = mCoordinates;
162 mCoordinates = GetNeighborCell(mCoordinates, moveLeft, moveRight, moveUp, moveDown);
164 if ((moveLeft && moveUp) || (moveUp && moveRight) || (moveRight && moveDown) || (moveDown && moveLeft))
166 mInverseSpeed = 1.4f / Speed;
170 mInverseSpeed = 1.0f / Speed;
177 #region Private Variables
179 Vector2 mPosition; // Position on the viewable map.
180 Point mCoordinates; // Position on the grid.
181 Point mLastCoordinates; // Last position on the grid.
182 float mInverseSpeed; // The time it takes to move from one cell to another.
183 float mTimeAccumulator; // Amount of time passed since last move.
184 bool mIsMoving; // Whether or not it is currently in the process of moving.