]> Dogcows Code - chaz/carfire/blobdiff - CarFire/CarFire/CarFire/Game.cs
Display should now follow correct player in a network game(Not Tested Yet!)
[chaz/carfire] / CarFire / CarFire / CarFire / Game.cs
index 38d86b8eb111e1f100f4f03934a6031575290f96..38ec627d1456dcff5531f055f9e4a3f45808872d 100644 (file)
@@ -9,18 +9,261 @@ using Microsoft.Xna.Framework.Input;
 \r
 namespace CarFire\r
 {\r
+    /// <summary>\r
+    /// Container class for the whole state of the game.\r
+    /// </summary>\r
+    public class GameState\r
+    {\r
+        #region Public Properties\r
+\r
+        public long FrameNumber { get { return mFrameNumber; } }\r
+\r
+        public long Checksum { get { return mChecksum; } }\r
+\r
+        public int NumberOfPlayers { get { return mNumberOfPlayers; } }\r
+\r
+        public Map Map;\r
+        public List<IEntity> Entities = new List<IEntity>();\r
+\r
+        #endregion\r
+\r
+\r
+        #region Public Methods\r
+\r
+        /// <summary>\r
+        /// Construct a game state container with the number of players.\r
+        /// </summary>\r
+        /// <param name="numPlayers">Number of players.</param>\r
+        public GameState(int numPlayers)\r
+        {\r
+            mNumberOfPlayers = numPlayers;\r
+            mFrameNumber = 0;\r
+\r
+            mIsGameOver = new bool[numPlayers];\r
+            mIsTerminated = new bool[numPlayers];\r
+\r
+            mMouseLocation = new Point[numPlayers];\r
+            mMouseButton = new bool[numPlayers];\r
+            mKeysDown = new List<Keys>[numPlayers];\r
+            for (int i = 0; i < numPlayers; i++) mKeysDown[i] = new List<Keys>();\r
+\r
+            mKeypressCount = new int[numPlayers];\r
+            mElapsedTime = 0;\r
+            mChecksum = 0;\r
+        }\r
+\r
+        \r
+        /// <summary>\r
+        /// Should be called by the Game class to advance the state\r
+        /// to the next frame.\r
+        /// </summary>\r
+        /// <param name="inputs">The inputs that occurred to be\r
+        /// applied this coming frame.</param>\r
+        /// <param name="milliseconds">Milliseconds; used for the checksum.</param>\r
+        public void AdvanceFrame(NextInputs inputs, long milliseconds)\r
+        {\r
+            mFrameNumber++;\r
+            mElapsedTime += milliseconds;\r
+\r
+            for (int player = 0; player < NumberOfPlayers; player++)\r
+            {\r
+                if (inputs.IsMousePressedChanged[player])\r
+                {\r
+                    mMouseButton[player] = inputs.MousePressed[player];\r
+                }\r
+\r
+                if (inputs.IsMouseLocationChanged[player])\r
+                {\r
+                    mMouseLocation[player] = inputs.MouseLocation[player];\r
+                }\r
+\r
+                foreach (Keys k in inputs.KeysPressed[player])\r
+                {\r
+                    if (!mKeysDown[player].Contains(k))\r
+                    {\r
+                        mKeysDown[player].Add(k);\r
+                        mKeypressCount[player]++;\r
+                    }\r
+                }\r
+\r
+                foreach (Keys k in inputs.KeysReleased[player]) mKeysDown[player].Remove(k);\r
+            }\r
+\r
+            ComputeChecksum();\r
+        }\r
+\r
+\r
+        /// <summary>\r
+        /// Get the mouse location for a player.\r
+        /// </summary>\r
+        /// <param name="playerNum">Player Number.</param>\r
+        /// <returns>Mouse location.</returns>\r
+        public Point GetMouseLocation(int playerNum)\r
+        {\r
+            return mMouseLocation[playerNum];\r
+        }\r
+\r
+        /// <summary>\r
+        /// Get the mouse button state for a player.\r
+        /// </summary>\r
+        /// <param name="playerNum">Player number.</param>\r
+        /// <returns>Mouse button state..</returns>\r
+        public bool GetMouseButton(int playerNum)\r
+        {\r
+            return mMouseButton[playerNum];\r
+        }\r
+\r
+        /// <summary>\r
+        /// Get the keyboard state for a player.\r
+        /// </summary>\r
+        /// <param name="playerNum">Player number.</param>\r
+        /// <returns>Keyboard state.</returns>\r
+        public List<Keys> GetKeysDown(int playerNum)\r
+        {\r
+            return mKeysDown[playerNum];\r
+        }\r
+\r
+        #endregion\r
+\r
+\r
+        #region Private Methods\r
+\r
+        // Calculates a checksum for debugging network synchronization issues.\r
+        long ComputeChecksum()\r
+        {\r
+            mChecksum += FrameNumber;\r
+            for (int i = 0; i < NumberOfPlayers; i++)\r
+            {\r
+                mChecksum = mChecksum + mKeypressCount[i];\r
+                mChecksum = mChecksum * 3 + (mIsGameOver[i] ? 1 : 2);\r
+                mChecksum = mChecksum * 3 + (mIsTerminated[i] ? 1 : 2);\r
+                foreach (Keys k in mKeysDown[i])\r
+                    mChecksum = mChecksum * 257 + (int)k;\r
+                mChecksum = mChecksum * 25789 + mMouseLocation[i].X * 259 + mMouseLocation[i].Y + 375;\r
+                mChecksum = mChecksum * 3 + (mMouseButton[i] ? 1 : 2);\r
+\r
+            }\r
+            mChecksum += mElapsedTime;\r
+\r
+            return mChecksum;\r
+        }\r
+\r
+        #endregion\r
+\r
+\r
+        #region Private Variables\r
+\r
+        int mNumberOfPlayers;\r
+        public Point[] mMouseLocation;\r
+        public bool[] mMouseButton;\r
+        public List<Keys>[] mKeysDown;\r
+\r
+        long mFrameNumber;\r
+\r
+        bool[] mIsGameOver;\r
+        bool[] mIsTerminated;\r
+\r
+        int[] mKeypressCount;\r
+        long mElapsedTime;\r
+        long mChecksum;\r
+\r
+        #endregion\r
+    }\r
+\r
+    /// <summary>\r
+    /// Container class for all the inputs for a single frame.\r
+    /// </summary>\r
+    public class NextInputs\r
+    {\r
+        public List<Keys>[] KeysPressed;\r
+        public List<Keys>[] KeysReleased;\r
+        public Point[] MouseLocation;\r
+        public bool[] IsMouseLocationChanged;\r
+        public bool[] MousePressed;\r
+        public bool[] IsMousePressedChanged;\r
+\r
+        public NextInputs(int numPlayers)\r
+        {\r
+            KeysPressed = new List<Keys>[numPlayers];\r
+            KeysReleased = new List<Keys>[numPlayers];\r
+            IsMouseLocationChanged = new bool[numPlayers];\r
+            MousePressed = new bool[numPlayers];\r
+            IsMousePressedChanged = new bool[numPlayers];\r
+            for (int i = 0; i < numPlayers; i++) KeysPressed[i] = new List<Keys>();\r
+            for (int i = 0; i < numPlayers; i++) KeysReleased[i] = new List<Keys>();\r
+        }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// The big kahuna.\r
+    /// </summary>\r
     public class Game : IDeterministicGame\r
     {\r
-        #region IDeterministicGame Members\r
+        #region Public Properties\r
+\r
+        /// <summary>\r
+        /// Get the content manager associated with this game.\r
+        /// </summary>\r
+        public ContentManager ContentManager { get { return mContentManager; } }\r
+\r
+        /// <summary>\r
+        /// Get the state.\r
+        /// </summary>\r
+        public GameState State;\r
 \r
+        public bool[,] Grid\r
+        {\r
+            get\r
+            {\r
+                bool[,] grid = State.Map.Grid;\r
+                foreach (IEntity entity in State.Entities)\r
+                {\r
+                    Point coordinates = entity.Coordinates;\r
+                    grid[coordinates.X, coordinates.Y] = true;\r
+                }\r
+                return grid;\r
+            }\r
+        }\r
+\r
+        #endregion\r
+\r
+\r
+        #region Public Methods\r
+\r
+        public bool IsCellOpen(Point point)\r
+        {\r
+            if (!State.Map.IsCellOpen(point)) return false;\r
+            foreach (IEntity entity in State.Entities)\r
+            {\r
+                if (entity.Coordinates == point) return false;\r
+            }\r
+            return true;\r
+        }\r
+\r
+        public Game()\r
+        {\r
+            mDisplay = new Display(this);\r
+        }\r
         public void LoadContent(ContentManager contentManager)\r
         {\r
+            mContentManager = contentManager;\r
+            mDisplay.LoadContent(contentManager);\r
         }\r
 \r
         public void UnloadContent()\r
         {\r
         }\r
 \r
+        private int GetPlayerNumber(Object playerIdentifier)\r
+        {\r
+            for (int i = 0; i < mPlayerIdentifiers.Length; i++)\r
+            {\r
+                if (mPlayerIdentifiers[i] == playerIdentifier) return i;\r
+            }\r
+            throw new Exception("Illegal player identifier" + playerIdentifier);\r
+        }\r
+\r
         public Vector2 PreferredScreenSize\r
         {\r
             get { return new Vector2(800, 600); }\r
@@ -38,11 +281,43 @@ namespace CarFire
 \r
         public void ResetGame(object[] playerIdentifiers, object thisPlayer)\r
         {\r
+            int numPlayers = playerIdentifiers.Count();\r
+\r
+            mPlayerIdentifiers = new object[numPlayers];\r
+            for (int i = 0; i < numPlayers; i++) mPlayerIdentifiers[i] = playerIdentifiers[i];\r
+\r
+            mThisPlayerID = GetPlayerNumber(thisPlayer);\r
+\r
+            State = new GameState(numPlayers);\r
+            mInputs = new NextInputs(numPlayers);\r
+\r
+            State.Map = mContentManager.Load<Map>("Maps/stable");\r
+            State.Map.Game = this;\r
+            State.Entities = State.Map.GetAllEntities();\r
+            Map.DefaultTile = mContentManager.Load<Texture2D>("default");\r
+\r
+            /*\r
+            mPlayers.Clear();\r
+            for (int i = 0; i < PlayerIdentifiers.Length; i++)\r
+            {\r
+                Human player = new Human(mMap, "");\r
+                mPlayers.Add(player);\r
+                mDisplay.AddCharacters(player);\r
+                mPlayers.Add(player);\r
+                mDisplay.AddCharacters(player);\r
+            }\r
+            this.playerIdentifiers = PlayerIdentifiers;\r
+            for (int i = 0; i < mPlayers.Count; i++) \r
+            {\r
+                Point starting = mMap.GetStartingPositionForPlayer(i + 1);\r
+                mPlayers[i].Spawn(new Vector2(starting.X, starting.Y));\r
+            }\r
+            */\r
         }\r
 \r
         public long CurrentFrameNumber\r
         {\r
-            get { return 0; }\r
+            get { return State.FrameNumber; }\r
         }\r
 \r
         public long CurrentChecksum\r
@@ -52,36 +327,67 @@ namespace CarFire
 \r
         public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed)\r
         {\r
+            //code from Prof Jensen's TestHarness\r
+            int player = GetPlayerNumber(playerIdentifier);\r
+\r
+            if (isKeyPressed && !mInputs.KeysPressed[player].Contains(key))\r
+                mInputs.KeysPressed[player].Add(key);\r
+\r
+            if (!isKeyPressed && !mInputs.KeysReleased[player].Contains(key))\r
+                mInputs.KeysReleased[player].Add(key);\r
+           \r
         }\r
 \r
         public void ApplyMouseLocationInput(object playerIdentifier, int x, int y)\r
         {\r
+\r
         }\r
 \r
         public void ApplyMouseButtonInput(object playerIdentifier, bool isButtonPressed)\r
         {\r
+\r
         }\r
 \r
         public bool IsGameOver(object playerIdentifier)\r
         {\r
-            return true;\r
+            return false;\r
         }\r
 \r
         public bool IsTerminated(object playerIdentifier)\r
         {\r
-            return true;\r
+            return false;\r
         }\r
 \r
-        public long Update(TimeSpan timespan)\r
+        public long Update(TimeSpan elapsedTime)\r
         {\r
-            return CurrentFrameNumber;\r
+            State.AdvanceFrame(mInputs, elapsedTime.Milliseconds);  // Apply the inputs, advance game state.\r
+            mDisplay.Update(elapsedTime, State, mThisPlayerID);\r
+            State.Entities.ForEach(delegate(IEntity e) { e.Update(elapsedTime); });\r
+            mInputs = new NextInputs(State.NumberOfPlayers);  // Start with inputs cleared on the next frame.\r
+            //mDisplay.Update(elapsedTime);\r
+            return State.FrameNumber;\r
+           \r
         }\r
 \r
         public long Draw(SpriteBatch spriteBatch)\r
         {\r
+            mDisplay.Draw(spriteBatch);\r
             return CurrentFrameNumber;\r
         }\r
 \r
         #endregion\r
+\r
+\r
+        #region Private Variables\r
+\r
+        Display mDisplay;\r
+\r
+        ContentManager mContentManager;\r
+        NextInputs mInputs;\r
+\r
+        Object[] mPlayerIdentifiers;\r
+        int mThisPlayerID;\r
+\r
+        #endregion\r
     }\r
 }\r
This page took 0.026227 seconds and 4 git commands to generate.