]> Dogcows Code - chaz/carfire/commitdiff
Smooth movement between cells.
authorCharles <Charles@92bb83a3-7c8f-8a45-bc97-515c4e399668>
Mon, 19 Apr 2010 20:05:26 +0000 (20:05 +0000)
committerCharles <Charles@92bb83a3-7c8f-8a45-bc97-515c4e399668>
Mon, 19 Apr 2010 20:05:26 +0000 (20:05 +0000)
Tested with two computers over the network..

git-svn-id: https://bd85.net/svn/cs3505_group@113 92bb83a3-7c8f-8a45-bc97-515c4e399668

CarFire/CarFire/CarFire/CarFire.csproj
CarFire/CarFire/CarFire/Display.cs
CarFire/CarFire/CarFire/Human.cs
CarFire/CarFire/CarFire/IPlayer.cs
CarFire/CarFire/CarFire/MovementManager.cs [new file with mode: 0644]
CarFire/CarFire/CarFire/ScreenManager.cs

index 2edc12d8b23734b901b1a2fa1eeaaa842f0c96a5..6548035b6c3c76a6bd78c464af151e63e920654d 100644 (file)
@@ -84,6 +84,7 @@
     </Reference>\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <Compile Include="MovementManager.cs" />\r
     <Compile Include="PathFinder.cs" />\r
     <Compile Include="ChatInfo.cs" />\r
     <Compile Include="Display.cs" />\r
index 5a85fdc9feddb648395256dccc0bf16af741bacc..9e06485af34a242af1bc86187e68eb02637eeba8 100644 (file)
@@ -117,7 +117,7 @@ namespace CarFire
                 if(mCharacters[j] != null)\r
                 for (int i = 0; i < mProjectiles.Count; i++)\r
                 {\r
-                    if (mProjectiles[i].GridX == mCharacters[j].GridX && mProjectiles[i].GridY == mCharacters[j].GridY)\r
+                    if (mProjectiles[i].GridX == mCharacters[j].Coordinates.X && mProjectiles[i].GridY == mCharacters[j].Coordinates.Y)\r
                     {\r
                         mCharacters[j].causeDamageTo(mProjectiles[i].Damage);\r
                         Console.WriteLine(mCharacters[j].Health);\r
@@ -134,22 +134,20 @@ namespace CarFire
                 {\r
                     if (state.keysDown[i].Contains(Keys.Enter))\r
                     {\r
-                        mCharacters[i] = (new Human(mMap, "", everything, projectile1, this));\r
-                        mCharacters[i].GridX = mMap.GetStartingPositionForPlayer(i + 1).X;\r
-                        mCharacters[i].GridY = mMap.GetStartingPositionForPlayer(i + 1).Y;\r
+                        mCharacters[i] = new Human(mMap, "", everything, projectile1, this, mMap.GetStartingPositionForPlayer(i+1));\r
                     }\r
                 }\r
                 //Regular player input updates\r
                 else\r
                 {\r
 \r
-                    mCharacters[i].MovePlayer(state.keysDown[i]);\r
+                    mCharacters[i].MovePlayer(timespan, state.keysDown[i]);\r
                    \r
                 }\r
             }\r
             if (mCharacters[0] != null)\r
             {\r
-                mMap.CenterCell = new Vector2(mCharacters[0].PixelX / Map.PixelsToUnitSquares, mCharacters[0].PixelY / Map.PixelsToUnitSquares);\r
+                mMap.CenterCell = mCharacters[0].Position;\r
             }\r
                 //Handle wall collisions of projectiles again...\r
             for (int i = 0; i < mProjectiles.Count; i++)\r
index 07b4222f97a6fff7c3a0b36072ea9d27b0a24110..168fa06f627a0d9024489cf8a7e23c59247cc46f 100644 (file)
@@ -25,23 +25,14 @@ namespace CarFire
         State state;\r
         String CharName;\r
         Map theMap;\r
-        int gridX;\r
-        int gridY;\r
         Texture2D charModel;\r
         Texture2D projectileModel;\r
         int health;\r
         int damage;\r
         int range;\r
         int score;\r
-        \r
-        //Used to smooth animations\r
-        bool isMoving;\r
-        float pixelX;\r
-        float pixelY;\r
-        int movementSteps;\r
-        int movementCoolDown;\r
-        float changeX;\r
-        float changeY;\r
+\r
+        MovementManager mMotion;\r
 \r
         bool visible;\r
         Display theDisplay;\r
@@ -51,7 +42,7 @@ namespace CarFire
         int projectileCoolDown;\r
         \r
 \r
-        public Human(Map _theMap, String Name, Texture2D model, Texture2D projectile, Display mDisplay)\r
+        public Human(Map _theMap, String Name, Texture2D model, Texture2D projectile, Display mDisplay, Point position)\r
         {\r
             theMap = _theMap;\r
             CharName = Name;\r
@@ -64,9 +55,9 @@ namespace CarFire
             charModel = model;\r
             projectileModel = projectile;\r
             projectileSpeed = 30;\r
-            //The number of animation steps between each square movement.\r
-            movementSteps = moveCoolDown -2;\r
-            \r
+\r
+            // Speed is the number of grid cells you can move through per second.\r
+            mMotion = new MovementManager(position, 5.0f);\r
         }\r
 \r
         public void LoadContent(ContentManager contentManager)\r
@@ -93,38 +84,18 @@ namespace CarFire
         /// <returns></returns>\r
         public long Draw(SpriteBatch spriteBatch)\r
         {\r
-            //If the sprite is moving there are still movement animations to do.\r
-            if (isMoving && movementSteps > 0)\r
-            {\r
-                movementSteps--;\r
-                pixelX = pixelX + changeX;\r
-                pixelY = pixelY + changeY;\r
-                Rectangle position3 = theMap.GetRectangleFromCoordinates(new Vector2(pixelX / Map.PixelsToUnitSquares, pixelY / Map.PixelsToUnitSquares));\r
-                spriteBatch.Draw(charModel, position3, Color.White);\r
-            }\r
-            // If the sprite is not moving then just draw it.\r
-            else\r
-            {\r
-                pixelX = gridX * Map.PixelsToUnitSquares;\r
-                pixelY = gridY * Map.PixelsToUnitSquares;\r
-                changeX = 0;\r
-                changeY = 0;\r
-                isMoving = false;\r
-                movementSteps = moveCoolDown - 2;\r
-                spriteBatch.Draw(charModel, theMap.GetRectangleFromCoordinates(gridX, gridY), Color.White);\r
-            }\r
+            Rectangle position = theMap.GetRectangleFromCoordinates(mMotion.Position);\r
+            spriteBatch.Draw(charModel, position, Color.White);\r
             return 0;\r
         }\r
 \r
-        public int GridX { get { return gridX; } set { gridX = value; } }\r
-        public int GridY { get { return gridY; } set { gridY = value; } }\r
-        public float PixelX { get { return pixelX; } }\r
-        public float PixelY { get { return pixelY; } }\r
         public int Health { get { return health; } }\r
-        public bool IsMoving { get { return isMoving; } }\r
         public int Score { get { return score; } }\r
         public bool alive { get { return health > 0; } }\r
 \r
+        public Vector2 Position { get { return mMotion.Position; } }\r
+        public Point Coordinates { get { return mMotion.Coordinates; } }\r
+\r
         public void causeDamageTo(int amount)\r
         {\r
             health -= amount;\r
@@ -137,104 +108,24 @@ namespace CarFire
         /// that is being moved to is an open space.\r
         /// </summary>\r
         /// <param name="keysPressed">A general list of keys that are pressed. Other keys can be included but only direction keys will be used</param>\r
-        public void MovePlayer(List<Keys> keysPressed)\r
+        public void MovePlayer(TimeSpan timeSpan, List<Keys> keysPressed)\r
         {\r
-            if(movementCoolDown > 0)\r
-                movementCoolDown--;\r
-            else if (movementCoolDown == 0)\r
+            bool moveLeft = keysPressed.Contains(Keys.Left);\r
+            bool moveRight = keysPressed.Contains(Keys.Right);\r
+            bool moveUp = keysPressed.Contains(Keys.Up);\r
+            bool moveDown = keysPressed.Contains(Keys.Down);\r
+\r
+            Point destination = MovementManager.GetNeighborCell(mMotion.Coordinates, moveLeft, moveRight, moveUp, moveDown);\r
+            if (theMap.IsCellOpen(destination))\r
             {\r
-                // move upleft\r
-                keysPressed.Contains<Keys>(Keys.Left);\r
-                if (keysPressed.Contains<Keys>(Keys.Up) && keysPressed.Contains<Keys>(Keys.Left) && theMap.IsCellOpen(gridX - 1, gridY - 1))\r
-                {\r
-                    pixelX = (float)(gridX * Map.PixelsToUnitSquares);\r
-                    pixelY = (float)(gridY * Map.PixelsToUnitSquares);\r
-                    gridX -= 1;\r
-                    gridY -= 1;\r
-                    movementCoolDown = moveCoolDown;\r
-                    isMoving = true;\r
-                  \r
-                    \r
-                }\r
-                // move upright\r
-                else if (keysPressed.Contains<Keys>(Keys.Up) && keysPressed.Contains<Keys>(Keys.Right) && theMap.IsCellOpen(gridX + 1, gridY - 1))\r
-                {\r
-                    pixelX = (float)(gridX * Map.PixelsToUnitSquares);\r
-                    pixelY = (float)(gridY * Map.PixelsToUnitSquares);\r
-                    gridX += 1;\r
-                    gridY -= 1;\r
-                    movementCoolDown = moveCoolDown;\r
-                    isMoving = true;\r
-                    \r
-                    \r
-                }\r
-                // move downleft\r
-                else if (keysPressed.Contains<Keys>(Keys.Down) && keysPressed.Contains<Keys>(Keys.Left) && theMap.IsCellOpen(gridX - 1, gridY + 1))\r
-                {\r
-                    pixelX = (float)(gridX * Map.PixelsToUnitSquares);\r
-                    pixelY = (float)(gridY * Map.PixelsToUnitSquares);\r
-                    gridX -= 1;\r
-                    gridY += 1;\r
-                    movementCoolDown = moveCoolDown;\r
-                    isMoving = true;\r
-                    \r
-                }\r
-                // move downright\r
-                else if (keysPressed.Contains<Keys>(Keys.Down) && keysPressed.Contains<Keys>(Keys.Right) && theMap.IsCellOpen(gridX + 1, gridY + 1))\r
-                {\r
-                    pixelX = (float)(gridX * Map.PixelsToUnitSquares);\r
-                    pixelY = (float)(gridY * Map.PixelsToUnitSquares);\r
-                    gridX += 1;\r
-                    gridY += 1;\r
-                    movementCoolDown = moveCoolDown;\r
-                    isMoving = true;\r
-                    \r
-                }\r
-                // move up\r
-                else if (keysPressed.Contains<Keys>(Keys.Up) && theMap.IsCellOpen(gridX, gridY - 1))\r
-                {\r
-                    pixelX = (float)(gridX * Map.PixelsToUnitSquares);\r
-                    pixelY = (float)(gridY * Map.PixelsToUnitSquares);\r
-                    state = State.up;\r
-                    gridY -= 1;\r
-                    movementCoolDown = moveCoolDown;\r
-                    isMoving = true;\r
-                    changeY = (float)(-Map.PixelsToUnitSquares / moveCoolDown);\r
-                }\r
-                // move down\r
-                else if (keysPressed.Contains<Keys>(Keys.Down) && theMap.IsCellOpen(gridX, gridY + 1))\r
-                {\r
-                    pixelX = (float)(gridX * Map.PixelsToUnitSquares);\r
-                    pixelY = (float)(gridY * Map.PixelsToUnitSquares);\r
-                    state = State.down;\r
-                    gridY += 1;\r
-                    movementCoolDown = moveCoolDown;\r
-                    isMoving = true;\r
-                    changeY = (float)(Map.PixelsToUnitSquares / moveCoolDown);\r
-                }\r
-                // move left\r
-                else if (keysPressed.Contains<Keys>(Keys.Left) && theMap.IsCellOpen(gridX - 1, gridY))\r
-                {\r
-                    pixelX = (float)(gridX * Map.PixelsToUnitSquares);\r
-                    pixelY = (float)(gridY * Map.PixelsToUnitSquares);\r
-                    state = State.left;\r
-                    gridX -= 1;\r
-                    movementCoolDown = moveCoolDown;\r
-                    isMoving = true;\r
-                    changeX = (float)(-Map.PixelsToUnitSquares / moveCoolDown);\r
-                }\r
-                // move right\r
-                else if (keysPressed.Contains<Keys>(Keys.Right) && theMap.IsCellOpen(gridX + 1, gridY))\r
-                {\r
-                    pixelX = (float)(gridX * Map.PixelsToUnitSquares);\r
-                    pixelY = (float)(gridY * Map.PixelsToUnitSquares);\r
-                    state = State.right;\r
-                    gridX += 1;\r
-                    movementCoolDown = moveCoolDown;\r
-                    isMoving = true;\r
-                    changeX = (float)(Map.PixelsToUnitSquares / moveCoolDown);\r
-                }\r
+                mMotion.Update(timeSpan, moveLeft, moveRight, moveUp, moveDown);\r
             }\r
+            else\r
+            {\r
+                mMotion.Update(timeSpan);\r
+            }\r
+\r
+\r
             if (projectileCoolDown > 0)\r
                 projectileCoolDown--;\r
             else if (projectileCoolDown == 0)\r
@@ -245,22 +136,26 @@ namespace CarFire
                     if (state == State.up)\r
                     {\r
                         projectileCoolDown = shootCoolDown;\r
-                        theDisplay.AddProjectiles(new Projectile(theMap, projectileModel, new Vector2(0, -projectileSpeed), GridX, GridY - 1));\r
+                        theDisplay.AddProjectiles(new Projectile(theMap, projectileModel,\r
+                            new Vector2(0, -projectileSpeed), Coordinates.X, Coordinates.Y - 1));\r
                     }\r
                     if (state == State.down)\r
                     {\r
                         projectileCoolDown = shootCoolDown;\r
-                        theDisplay.AddProjectiles(new Projectile(theMap, projectileModel, new Vector2(0, projectileSpeed), GridX, GridY + 1));\r
+                        theDisplay.AddProjectiles(new Projectile(theMap, projectileModel,\r
+                            new Vector2(0, projectileSpeed), Coordinates.X, Coordinates.Y + 1));\r
                     }\r
                     if (state == State.right)\r
                     {\r
                         projectileCoolDown = shootCoolDown;\r
-                        theDisplay.AddProjectiles(new Projectile(theMap, projectileModel, new Vector2(projectileSpeed, 0), GridX + 1, GridY));\r
+                        theDisplay.AddProjectiles(new Projectile(theMap, projectileModel,\r
+                            new Vector2(projectileSpeed, 0), Coordinates.X + 1, Coordinates.Y));\r
                     }\r
                     if (state == State.left)\r
                     {\r
                         projectileCoolDown = shootCoolDown;\r
-                        theDisplay.AddProjectiles(new Projectile(theMap, projectileModel, new Vector2(-projectileSpeed, 0), GridX - 1, GridY));\r
+                        theDisplay.AddProjectiles(new Projectile(theMap, projectileModel,\r
+                            new Vector2(-projectileSpeed, 0), Coordinates.X - 1, Coordinates.Y));\r
                     }\r
                 }\r
             }\r
@@ -274,8 +169,8 @@ namespace CarFire
 \r
         public void Spawn(Vector2 spawn)\r
         {\r
-            gridX = (int)spawn.X;\r
-            gridY = (int)spawn.Y;\r
+            //gridX = (int)spawn.X;\r
+            //gridY = (int)spawn.Y;\r
             visible = true;\r
         }\r
 \r
index b60ef1a23aa3d784dd3b7c4a7b45c102e976a353..a65ced5f83dfbfe0701b366f1c39777bebd4bb5c 100644 (file)
@@ -17,16 +17,13 @@ namespace CarFire
         long Draw(SpriteBatch spriteBatch);\r
         int Health { get; }\r
         void causeDamageTo(int amount);\r
-        int GridX { get; set; }\r
-        int GridY { get; set; }\r
-        float PixelX { get; }\r
-        float PixelY { get; }\r
-        bool IsMoving { get; }\r
+        Vector2 Position { get; }\r
+        Point Coordinates { get; }\r
     }\r
 \r
     public interface IPlayer : ICharacter\r
     {\r
-        void MovePlayer(List<Keys> keysPressed);\r
+        void MovePlayer(TimeSpan timeSpan, List<Keys> keysPressed);\r
         int Score { get; }\r
         void powerUp(int amount);\r
         void Spawn(Vector2 spawn);\r
diff --git a/CarFire/CarFire/CarFire/MovementManager.cs b/CarFire/CarFire/CarFire/MovementManager.cs
new file mode 100644 (file)
index 0000000..372be6c
--- /dev/null
@@ -0,0 +1,188 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using Microsoft.Xna.Framework;\r
+\r
+namespace CarFire\r
+{\r
+    /// <summary>\r
+    /// A class to manage the motion of objects on a grid of cells.\r
+    /// Each update you can pass a direction and the manager will move\r
+    /// the position to that point while also enforcing a speed limit.\r
+    /// This class does not detect collisions, so care must be taken\r
+    /// to only pass directions to a walkable cell during an update.\r
+    /// </summary>\r
+    public class MovementManager\r
+    {\r
+        #region Public Properties\r
+\r
+        /// <summary>\r
+        /// Get the current position in map coordinates.  This is the\r
+        /// smooth, interpolated set of coordinates.\r
+        /// </summary>\r
+        public Vector2 Position { get { return mPosition; } }\r
+\r
+        /// <summary>\r
+        /// Get the grid coordinates where the object is at or\r
+        /// is moving to.\r
+        /// </summary>\r
+        public Point Coordinates { get { return mCoordinates; } }\r
+\r
+        /// <summary>\r
+        /// Get and set the speed of movement in grid cells / second.\r
+        /// </summary>\r
+        public float Speed;\r
+\r
+        #endregion\r
+\r
+\r
+        #region Public Methods\r
+\r
+        /// <summary>\r
+        /// Construct a movement manager with the initial position of\r
+        /// the thing you want to track.\r
+        /// </summary>\r
+        /// <param name="position">Grid coordinates.</param>\r
+        public MovementManager(Point position)\r
+        {\r
+            mPosition = new Vector2((float)position.X, (float)position.Y);\r
+            mCoordinates = position;\r
+            mLastCoordinates = position;\r
+            Speed = 1.0f;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Construct a movement manager with the initial position of\r
+        /// the thing you want to track and its speed.\r
+        /// </summary>\r
+        /// <param name="position">Grid coordinates.</param>\r
+        /// <param name="speed">Speed: Grid cells per second.</param>\r
+        public MovementManager(Point position, float speed)\r
+        {\r
+            mPosition = new Vector2((float)position.X, (float)position.Y);\r
+            mCoordinates = position;\r
+            mLastCoordinates = position;\r
+            Speed = speed;\r
+        }\r
+\r
+\r
+        /// <summary>\r
+        /// Update the movement manager with the timeslice and no directions.\r
+        /// </summary>\r
+        /// <param name="timeSpan">The timeslice.</param>\r
+        public void Update(TimeSpan timeSpan)\r
+        {\r
+            Update(timeSpan, false, false, false, false);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Update the movement manager with the timeslice and the directions\r
+        /// the object is supposed to go.  The directions will be ignored if the\r
+        /// object is currently in transit from one cell to another.\r
+        /// </summary>\r
+        /// <param name="timeSpan">The timeslice.</param>\r
+        /// <param name="moveLeft">Want to move left.</param>\r
+        /// <param name="moveRight">Want to move right.</param>\r
+        /// <param name="moveUp">Want to move up.</param>\r
+        /// <param name="moveDown">Want to move down.</param>\r
+        public void Update(TimeSpan timeSpan, bool moveLeft, bool moveRight, bool moveUp, bool moveDown)\r
+        {\r
+            float passedTime = (float)timeSpan.TotalSeconds;\r
+\r
+            bool requestMove = (moveLeft ^ moveRight) || (moveUp ^ moveDown);\r
+            if (!mIsMoving && requestMove)\r
+            {\r
+                UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);\r
+\r
+                mIsMoving = true;\r
+                mTimeAccumulator = passedTime;\r
+\r
+                RecalculatePosition(mTimeAccumulator / mInverseSpeed);\r
+            }\r
+            else if (mIsMoving)\r
+            {\r
+                mTimeAccumulator += passedTime;\r
+\r
+                float alpha = mTimeAccumulator / mInverseSpeed;\r
+                if (alpha >= 1.0f)\r
+                {\r
+                    if (requestMove)\r
+                    {\r
+                        mTimeAccumulator = mTimeAccumulator - mInverseSpeed;\r
+                        alpha = mTimeAccumulator / mInverseSpeed;\r
+\r
+                        UpdateCoordinates(moveLeft, moveRight, moveUp, moveDown);\r
+                    }\r
+                    else\r
+                    {\r
+                        mIsMoving = false;\r
+                        alpha = 1.0f;\r
+                    }\r
+                }\r
+\r
+                RecalculatePosition(alpha);\r
+            }\r
+        }\r
+\r
+\r
+        /// <summary>\r
+        /// Helper method to get neighbor cells from a point and directions.\r
+        /// </summary>\r
+        /// <param name="point">The point.</param>\r
+        /// <param name="left">To the left.</param>\r
+        /// <param name="right">To the right.</param>\r
+        /// <param name="up">Above.</param>\r
+        /// <param name="down">Below.</param>\r
+        /// <returns>The neighbor cell coordinates.</returns>\r
+        public static Point GetNeighborCell(Point point, bool left, bool right, bool up, bool down)\r
+        {\r
+            if (left) point.X--;\r
+            if (right) point.X++;\r
+            if (up) point.Y--;\r
+            if (down) point.Y++;\r
+            return point;\r
+        }\r
+\r
+        #endregion\r
+\r
+\r
+        #region Private Methods\r
+\r
+        void RecalculatePosition(float alpha)\r
+        {\r
+            Console.WriteLine("last: " + mLastCoordinates + ", now: " + mCoordinates + ", alpha: " + alpha);\r
+            mPosition.X = (float)mLastCoordinates.X + alpha * ((float)mCoordinates.X - (float)mLastCoordinates.X);\r
+            mPosition.Y = (float)mLastCoordinates.Y + alpha * ((float)mCoordinates.Y - (float)mLastCoordinates.Y);\r
+        }\r
+\r
+        void UpdateCoordinates(bool moveLeft, bool moveRight, bool moveUp, bool moveDown)\r
+        {\r
+            mLastCoordinates = mCoordinates;\r
+            mCoordinates = GetNeighborCell(mCoordinates, moveLeft, moveRight, moveUp, moveDown);\r
+\r
+            if ((moveLeft && moveUp) || (moveUp && moveRight) || (moveRight && moveDown) || (moveDown && moveLeft))\r
+            {\r
+                mInverseSpeed = 1.4f / Speed;\r
+            }\r
+            else\r
+            {\r
+                mInverseSpeed = 1.0f / Speed;\r
+            }\r
+        }\r
+\r
+        #endregion\r
+\r
+\r
+        #region Private Variables\r
+\r
+        Vector2 mPosition;              // Position on the viewable map.\r
+        Point mCoordinates;             // Position on the grid.\r
+        Point mLastCoordinates;         // Last position on the grid.\r
+        float mInverseSpeed;            // The time it takes to move from one cell to another.\r
+        float mTimeAccumulator;         // Amount of time passed since last move.\r
+        bool mIsMoving;                 // Whether or not it is currently in the process of moving.\r
+\r
+        #endregion\r
+    }\r
+}\r
index e4dc0f452ec0793a9a35166aa39ded04b5498314..b7a30b5c39f8b689bd21ea00b72e3b22800930e8 100644 (file)
@@ -365,7 +365,7 @@ namespace CarFire
                             }\r
 \r
                             //allows host to start the game when all players are ready, change count below to different number for testing with less then 4 players\r
-                            if (allReady && players.Count <= 1 && localPlayer == players[0])\r
+                            if (allReady && players.Count <= 4 && localPlayer == players[0])\r
                             {\r
                                 if (currentKeyboardState.IsKeyDown(Keys.B) && previousKeyboardState.IsKeyUp(Keys.B))\r
                                 {\r
This page took 0.041313 seconds and 4 git commands to generate.