X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fcarfire;a=blobdiff_plain;f=CarFire%2FCarFire%2FCarFire%2FMovementManager.cs;fp=CarFire%2FCarFire%2FCarFire%2FMovementManager.cs;h=372be6c23deab452650958f305729077de272b4c;hp=0000000000000000000000000000000000000000;hb=f31f4ae920ff902f4cd4fb64f5e6ccf0d5e58402;hpb=0b53fe63e2a9354e4c52506e2012065d15bbcff1
diff --git a/CarFire/CarFire/CarFire/MovementManager.cs b/CarFire/CarFire/CarFire/MovementManager.cs
new file mode 100644
index 0000000..372be6c
--- /dev/null
+++ b/CarFire/CarFire/CarFire/MovementManager.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Xna.Framework;
+
+namespace CarFire
+{
+ ///
+ /// A class to manage the motion of objects on a grid of cells.
+ /// Each update you can pass a direction and the manager will move
+ /// the position to that point while also enforcing a speed limit.
+ /// This class does not detect collisions, so care must be taken
+ /// to only pass directions to a walkable cell during an update.
+ ///
+ public class MovementManager
+ {
+ #region Public Properties
+
+ ///
+ /// Get the current position in map coordinates. This is the
+ /// smooth, interpolated set of coordinates.
+ ///
+ public Vector2 Position { get { return mPosition; } }
+
+ ///
+ /// Get the grid coordinates where the object is at or
+ /// is moving to.
+ ///
+ public Point Coordinates { get { return mCoordinates; } }
+
+ ///
+ /// Get and set the speed of movement in grid cells / second.
+ ///
+ public float Speed;
+
+ #endregion
+
+
+ #region Public Methods
+
+ ///
+ /// Construct a movement manager with the initial position of
+ /// the thing you want to track.
+ ///
+ /// Grid coordinates.
+ public MovementManager(Point position)
+ {
+ mPosition = new Vector2((float)position.X, (float)position.Y);
+ mCoordinates = position;
+ mLastCoordinates = position;
+ Speed = 1.0f;
+ }
+
+ ///
+ /// Construct a movement manager with the initial position of
+ /// the thing you want to track and its speed.
+ ///
+ /// Grid coordinates.
+ /// Speed: Grid cells per second.
+ public MovementManager(Point position, float speed)
+ {
+ mPosition = new Vector2((float)position.X, (float)position.Y);
+ mCoordinates = position;
+ mLastCoordinates = position;
+ Speed = speed;
+ }
+
+
+ ///
+ /// Update the movement manager with the timeslice and no directions.
+ ///
+ /// The timeslice.
+ public void Update(TimeSpan timeSpan)
+ {
+ Update(timeSpan, false, false, false, false);
+ }
+
+ ///
+ /// Update the movement manager with the timeslice and the directions
+ /// the object is supposed to go. The directions will be ignored if the
+ /// object is currently in transit from one cell to another.
+ ///
+ /// The timeslice.
+ /// Want to move left.
+ /// Want to move right.
+ /// Want to move up.
+ /// Want to move down.
+ public void Update(TimeSpan timeSpan, bool moveLeft, bool moveRight, bool moveUp, bool moveDown)
+ {
+ float passedTime = (float)timeSpan.TotalSeconds;
+
+ bool requestMove = (moveLeft ^ moveRight) || (moveUp ^ moveDown);
+ if (!mIsMoving && requestMove)
+ {
+ UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);
+
+ mIsMoving = true;
+ mTimeAccumulator = passedTime;
+
+ RecalculatePosition(mTimeAccumulator / mInverseSpeed);
+ }
+ else if (mIsMoving)
+ {
+ mTimeAccumulator += passedTime;
+
+ float alpha = mTimeAccumulator / mInverseSpeed;
+ if (alpha >= 1.0f)
+ {
+ if (requestMove)
+ {
+ mTimeAccumulator = mTimeAccumulator - mInverseSpeed;
+ alpha = mTimeAccumulator / mInverseSpeed;
+
+ UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);
+ }
+ else
+ {
+ mIsMoving = false;
+ alpha = 1.0f;
+ }
+ }
+
+ RecalculatePosition(alpha);
+ }
+ }
+
+
+ ///
+ /// Helper method to get neighbor cells from a point and directions.
+ ///
+ /// The point.
+ /// To the left.
+ /// To the right.
+ /// Above.
+ /// Below.
+ /// The neighbor cell coordinates.
+ public static Point GetNeighborCell(Point point, bool left, bool right, bool up, bool down)
+ {
+ if (left) point.X--;
+ if (right) point.X++;
+ if (up) point.Y--;
+ if (down) point.Y++;
+ return point;
+ }
+
+ #endregion
+
+
+ #region Private Methods
+
+ void RecalculatePosition(float alpha)
+ {
+ Console.WriteLine("last: " + mLastCoordinates + ", now: " + mCoordinates + ", alpha: " + alpha);
+ mPosition.X = (float)mLastCoordinates.X + alpha * ((float)mCoordinates.X - (float)mLastCoordinates.X);
+ mPosition.Y = (float)mLastCoordinates.Y + alpha * ((float)mCoordinates.Y - (float)mLastCoordinates.Y);
+ }
+
+ void UpdateCoordinates(bool moveLeft, bool moveRight, bool moveUp, bool moveDown)
+ {
+ mLastCoordinates = mCoordinates;
+ mCoordinates = GetNeighborCell(mCoordinates, moveLeft, moveRight, moveUp, moveDown);
+
+ if ((moveLeft && moveUp) || (moveUp && moveRight) || (moveRight && moveDown) || (moveDown && moveLeft))
+ {
+ mInverseSpeed = 1.4f / Speed;
+ }
+ else
+ {
+ mInverseSpeed = 1.0f / Speed;
+ }
+ }
+
+ #endregion
+
+
+ #region Private Variables
+
+ Vector2 mPosition; // Position on the viewable map.
+ Point mCoordinates; // Position on the grid.
+ Point mLastCoordinates; // Last position on the grid.
+ float mInverseSpeed; // The time it takes to move from one cell to another.
+ float mTimeAccumulator; // Amount of time passed since last move.
+ bool mIsMoving; // Whether or not it is currently in the process of moving.
+
+ #endregion
+ }
+}