]> Dogcows Code - chaz/carfire/blob - CarFire/CarFire/CarFire/MovementManager.cs
Smooth movement between cells.
[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 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.
15 /// </summary>
16 public class MovementManager
17 {
18 #region Public Properties
19
20 /// <summary>
21 /// Get the current position in map coordinates. This is the
22 /// smooth, interpolated set of coordinates.
23 /// </summary>
24 public Vector2 Position { get { return mPosition; } }
25
26 /// <summary>
27 /// Get the grid coordinates where the object is at or
28 /// is moving to.
29 /// </summary>
30 public Point Coordinates { get { return mCoordinates; } }
31
32 /// <summary>
33 /// Get and set the speed of movement in grid cells / second.
34 /// </summary>
35 public float Speed;
36
37 #endregion
38
39
40 #region Public Methods
41
42 /// <summary>
43 /// Construct a movement manager with the initial position of
44 /// the thing you want to track.
45 /// </summary>
46 /// <param name="position">Grid coordinates.</param>
47 public MovementManager(Point position)
48 {
49 mPosition = new Vector2((float)position.X, (float)position.Y);
50 mCoordinates = position;
51 mLastCoordinates = position;
52 Speed = 1.0f;
53 }
54
55 /// <summary>
56 /// Construct a movement manager with the initial position of
57 /// the thing you want to track and its speed.
58 /// </summary>
59 /// <param name="position">Grid coordinates.</param>
60 /// <param name="speed">Speed: Grid cells per second.</param>
61 public MovementManager(Point position, float speed)
62 {
63 mPosition = new Vector2((float)position.X, (float)position.Y);
64 mCoordinates = position;
65 mLastCoordinates = position;
66 Speed = speed;
67 }
68
69
70 /// <summary>
71 /// Update the movement manager with the timeslice and no directions.
72 /// </summary>
73 /// <param name="timeSpan">The timeslice.</param>
74 public void Update(TimeSpan timeSpan)
75 {
76 Update(timeSpan, false, false, false, false);
77 }
78
79 /// <summary>
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.
83 /// </summary>
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)
90 {
91 float passedTime = (float)timeSpan.TotalSeconds;
92
93 bool requestMove = (moveLeft ^ moveRight) || (moveUp ^ moveDown);
94 if (!mIsMoving && requestMove)
95 {
96 UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);
97
98 mIsMoving = true;
99 mTimeAccumulator = passedTime;
100
101 RecalculatePosition(mTimeAccumulator / mInverseSpeed);
102 }
103 else if (mIsMoving)
104 {
105 mTimeAccumulator += passedTime;
106
107 float alpha = mTimeAccumulator / mInverseSpeed;
108 if (alpha >= 1.0f)
109 {
110 if (requestMove)
111 {
112 mTimeAccumulator = mTimeAccumulator - mInverseSpeed;
113 alpha = mTimeAccumulator / mInverseSpeed;
114
115 UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);
116 }
117 else
118 {
119 mIsMoving = false;
120 alpha = 1.0f;
121 }
122 }
123
124 RecalculatePosition(alpha);
125 }
126 }
127
128
129 /// <summary>
130 /// Helper method to get neighbor cells from a point and directions.
131 /// </summary>
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)
139 {
140 if (left) point.X--;
141 if (right) point.X++;
142 if (up) point.Y--;
143 if (down) point.Y++;
144 return point;
145 }
146
147 #endregion
148
149
150 #region Private Methods
151
152 void RecalculatePosition(float alpha)
153 {
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);
157 }
158
159 void UpdateCoordinates(bool moveLeft, bool moveRight, bool moveUp, bool moveDown)
160 {
161 mLastCoordinates = mCoordinates;
162 mCoordinates = GetNeighborCell(mCoordinates, moveLeft, moveRight, moveUp, moveDown);
163
164 if ((moveLeft && moveUp) || (moveUp && moveRight) || (moveRight && moveDown) || (moveDown && moveLeft))
165 {
166 mInverseSpeed = 1.4f / Speed;
167 }
168 else
169 {
170 mInverseSpeed = 1.0f / Speed;
171 }
172 }
173
174 #endregion
175
176
177 #region Private Variables
178
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.
185
186 #endregion
187 }
188 }
This page took 0.044743 seconds and 5 git commands to generate.