+ /// <summary>\r
+ /// Container class for the whole state of the game.\r
+ /// </summary>\r
+ public class GameState\r
+ {\r
+ #region Public Properties\r
+ private const int hitMonsterScore = 20;\r
+ private const int killMonsterScore = 100;\r
+ public int HitMonsterScore { get { return hitMonsterScore; } }\r
+ public int KillMonsterScore { get { return killMonsterScore; } }\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
+ public List<Projectile> mProjectiles = new List<Projectile>();\r
+ public Player[] mCharacters;\r
+ public Display mDisplay;\r
+ public AI AIData;\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
+ mCharacters = new Player[numPlayers];\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