]> Dogcows Code - chaz/carfire/blob - CarFire/CarFire/CarFire/MovementManager.cs
Player can now stop and 'aim' by pressing left control.
[chaz/carfire] / CarFire / CarFire / CarFire / MovementManager.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using Microsoft.Xna.Framework;
6
7 namespace CarFire
8 {
9 /// <summary>
10 /// A type for a direction, including diagonals.
11 /// </summary>
12 public enum Direction
13 {
14 Down, // Default direction is down.
15 Left,
16 UpperLeft,
17 Up,
18 UpperRight,
19 Right,
20 LowerRight,
21 LowerLeft,
22 None
23 }
24
25
26 /// <summary>
27 /// A class to manage the motion of objects on a grid of cells.
28 /// Each update you can pass a direction and the manager will move
29 /// the position to that point while also enforcing a speed limit.
30 /// This class does not detect collisions, so care must be taken
31 /// to only pass directions to a walkable cell during an update.
32 /// </summary>
33 public class MovementManager
34 {
35 #region Public Properties
36
37 /// <summary>
38 /// Get the current position in map coordinates. This is the
39 /// smooth, interpolated set of coordinates.
40 /// </summary>
41 public Vector2 Position { get { return mPosition; } }
42
43 /// <summary>
44 /// Get the grid coordinates where the object is at or
45 /// is moving to.
46 /// </summary>
47 public Point Coordinates { get { return mCoordinates; } }
48
49 /// <summary>
50 /// Get and set the speed of movement in grid cells / second.
51 /// </summary>
52 public float Speed;
53
54 /// <summary>
55 /// Get whether or not the object is moving.
56 /// </summary>
57 public bool IsMoving { get { return mIsMoving; } }
58
59 /// <summary>
60 /// Get the direction the object is facing.
61 /// </summary>
62 public Direction Direction { get { return mDirection; } }
63
64 #endregion
65
66
67 #region Public Methods
68
69 /// <summary>
70 /// Construct a movement manager with the initial position of
71 /// the thing you want to track.
72 /// </summary>
73 /// <param name="position">Grid coordinates.</param>
74 public MovementManager(Point position)
75 {
76 mPosition = new Vector2((float)position.X, (float)position.Y);
77 mCoordinates = position;
78 mLastCoordinates = position;
79 Speed = 1.0f;
80 }
81
82 /// <summary>
83 /// Construct a movement manager with the initial position of
84 /// the thing you want to track and its speed.
85 /// </summary>
86 /// <param name="position">Grid coordinates.</param>
87 /// <param name="speed">Speed: Grid cells per second.</param>
88 public MovementManager(Point position, float speed)
89 {
90 mPosition = new Vector2((float)position.X, (float)position.Y);
91 mCoordinates = position;
92 mLastCoordinates = position;
93 Speed = speed;
94 }
95
96
97 /// <summary>
98 /// Update the movement manager with the timeslice and no directions.
99 /// </summary>
100 /// <param name="timeSpan">The timeslice.</param>
101 public void Update(TimeSpan timeSpan)
102 {
103 Update(timeSpan, false, false, false, false);
104 }
105
106 /// <summary>
107 /// Update the movement manager with the timeslice and the directions
108 /// the object is supposed to go. The directions will be ignored if the
109 /// object is currently in transit from one cell to another.
110 /// </summary>
111 /// <param name="timeSpan">The timeslice.</param>
112 /// <param name="moveLeft">Want to move left.</param>
113 /// <param name="moveRight">Want to move right.</param>
114 /// <param name="moveUp">Want to move up.</param>
115 /// <param name="moveDown">Want to move down.</param>
116 public void Update(TimeSpan timeSpan, bool moveLeft, bool moveRight, bool moveUp, bool moveDown)
117 {
118 float passedTime = (float)timeSpan.TotalSeconds;
119
120 bool requestMove = (moveLeft ^ moveRight) || (moveUp ^ moveDown);
121 if (!mIsMoving && requestMove)
122 {
123 mTimeAccumulator = passedTime;
124
125 mIsMoving = true;
126 UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);
127 mDirection = GetDirection(moveLeft, moveRight, moveUp, moveDown);
128
129 RecalculatePosition(mTimeAccumulator / mInverseSpeed);
130 }
131 else if (mIsMoving)
132 {
133 mTimeAccumulator += passedTime;
134
135 float alpha = mTimeAccumulator / mInverseSpeed;
136 if (alpha >= 1.0f)
137 {
138 if (requestMove)
139 {
140 mTimeAccumulator = mTimeAccumulator - mInverseSpeed;
141 alpha = mTimeAccumulator / mInverseSpeed;
142
143 UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);
144 mDirection = GetDirection(moveLeft, moveRight, moveUp, moveDown);
145 }
146 else
147 {
148 mIsMoving = false;
149 alpha = 1.0f;
150 }
151 }
152
153 RecalculatePosition(alpha);
154 }
155 }
156 public void LockUpdate(TimeSpan timeSpan, bool moveLeft, bool moveRight, bool moveUp, bool moveDown)
157 {
158 float passedTime = (float)timeSpan.TotalSeconds;
159 if (moveLeft == true || moveRight == true || moveUp == true || moveDown == true)
160 {
161 mDirection = GetDirection(moveLeft, moveRight, moveUp, moveDown);
162 }
163 if (mIsMoving)
164 {
165 mTimeAccumulator += passedTime;
166
167 float alpha = mTimeAccumulator / mInverseSpeed;
168 if (alpha >= 1.0f)
169 {
170 mIsMoving = false;
171 alpha = 1.0f;
172 }
173
174 RecalculatePosition(alpha);
175 }
176 }
177
178
179 /// <summary>
180 /// Helper method to get neighbor cells from a point and directions.
181 /// </summary>
182 /// <param name="point">The point.</param>
183 /// <param name="left">To the left.</param>
184 /// <param name="right">To the right.</param>
185 /// <param name="up">Above.</param>
186 /// <param name="down">Below.</param>
187 /// <returns>The neighbor cell coordinates.</returns>
188 public static Point GetNeighborCell(Point point, bool left, bool right, bool up, bool down)
189 {
190 if (left) point.X--;
191 if (right) point.X++;
192 if (up) point.Y--;
193 if (down) point.Y++;
194 return point;
195 }
196
197 /// <summary>
198 /// Helper method to get a Direction type from directions.
199 /// </summary>
200 /// <param name="left">Left.</param>
201 /// <param name="right">Right.</param>
202 /// <param name="up">Up.</param>
203 /// <param name="down">Down.</param>
204 /// <returns>The direction.</returns>
205 public static Direction GetDirection(bool left, bool right, bool up, bool down)
206 {
207 if (left && !right)
208 {
209 if (up) return Direction.UpperLeft;
210 else if (down) return Direction.LowerLeft;
211 else return Direction.Left;
212 }
213 else if (right && !left)
214 {
215 if (up) return Direction.UpperRight;
216 else if (down) return Direction.LowerRight;
217 else return Direction.Right;
218 }
219 else if (up) return Direction.Up;
220 else if (down) return Direction.Down;
221 else return Direction.None;
222 }
223
224 #endregion
225
226
227 #region Private Methods
228
229 void RecalculatePosition(float alpha)
230 {
231 //Console.WriteLine("last: " + mLastCoordinates + ", now: " + mCoordinates + ", alpha: " + alpha);
232 mPosition.X = (float)mLastCoordinates.X + alpha * ((float)mCoordinates.X - (float)mLastCoordinates.X);
233 mPosition.Y = (float)mLastCoordinates.Y + alpha * ((float)mCoordinates.Y - (float)mLastCoordinates.Y);
234 }
235
236 void UpdateCoordinates(bool moveLeft, bool moveRight, bool moveUp, bool moveDown)
237 {
238 mLastCoordinates = mCoordinates;
239 mCoordinates = GetNeighborCell(mCoordinates, moveLeft, moveRight, moveUp, moveDown);
240
241 if ((moveLeft && moveUp) || (moveUp && moveRight) || (moveRight && moveDown) || (moveDown && moveLeft))
242 {
243 mInverseSpeed = 1.4f / Speed;
244 }
245 else
246 {
247 mInverseSpeed = 1.0f / Speed;
248 }
249 }
250
251 #endregion
252
253
254 #region Private Variables
255
256 Vector2 mPosition; // Position on the viewable map.
257 Point mCoordinates; // Position on the grid.
258 Point mLastCoordinates; // Last position on the grid.
259 float mInverseSpeed; // The time it takes to move from one cell to another.
260 float mTimeAccumulator; // Amount of time passed since last move.
261 bool mIsMoving; // Whether or not it is currently in the process of moving.
262 Direction mDirection; // The direction the object is facing.
263
264 #endregion
265 }
266 }
This page took 0.052415 seconds and 5 git commands to generate.