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