+ 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
+ #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
+ public class Game : IDeterministicGame\r
+ {\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 = (bool[,])State.Map.Grid.Clone();\r
+ foreach (IEntity entity in State.Entities)\r
+ {\r
+ Point coordinates = entity.Coordinates;\r
+ grid[coordinates.X, coordinates.Y] = false;\r
+ }\r
+ foreach (Player player in State.mCharacters)\r
+ {\r
+ if (player == null) continue;\r
+ Point coordinates = player.Coordinates;\r
+ grid[coordinates.X, coordinates.Y] = false;\r
+ }\r
+ return grid;\r
+ }\r
+ }\r
+\r
+ #endregion\r
+\r
+\r
+ #region Public Methods\r
+\r
+ /// <summary>\r
+ /// Get an entity at a certain place on the map.\r
+ /// </summary>\r
+ /// <param name="point">The coordinates.</param>\r
+ /// <returns>The entity, or null if none is at that location.</returns>\r
+ public IEntity GetEntityAtCoordinates(Point point)\r
+ {\r
+ foreach (IEntity entity in State.Entities)\r
+ {\r
+ if (entity.Coordinates == point) return entity;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Get a player at a certain place on the map.\r
+ /// </summary>\r
+ /// <param name="point">The coordinates.</param>\r
+ /// <returns>The player, or null if none is at that location.</returns>\r
+ public Player GetPlayerAtCoordinates(Point point)\r
+ {\r
+ foreach (Player player in State.mCharacters)\r
+ {\r
+ if (player != null && player.Coordinates == point) return player;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Determine if a cell is open, depending on the static scenery\r
+ /// of the map and if there are any collidable entities.\r
+ /// </summary>\r
+ /// <param name="point">The coordinates.</param>\r
+ /// <returns>True if the cell is open; false otherwise.</returns>\r
+ public bool IsCellOpen(Point point)\r
+ {\r
+ if (!State.Map.IsCellOpen(point)) return false;\r
+ IEntity entity = GetEntityAtCoordinates(point);\r
+ if (entity != null && entity.IsCollidable) return false;\r
+ Player player = GetPlayerAtCoordinates(point);\r
+ if (player != null) return false;\r
+ return true;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Remove a specific entity from the game. The entity can still\r
+ /// be tracked some other way, but it won't included when the game is\r
+ /// updating and drawing stuff.\r
+ /// </summary>\r
+ /// <param name="entity">The entity.</param>\r
+ /// <returns>The entity that was removed, or null if no entity was removed.</returns>\r
+ public IEntity RemoveEntity(IEntity entity)\r
+ {\r
+ if (State.Entities.Remove(entity)) return entity;\r
+ return null;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Move on to the next map, and advance the level.\r
+ /// </summary>\r
+ public void AdvanceLevel()\r
+ {\r
+ // TODO: Load the next map, etc...\r
+ //TODO somehow get next map\r
+ State.Entities.Clear();\r
+ String nextMap = State.Map.Next;\r
+ State.Map = mContentManager.Load<Map>("Maps/"+nextMap);\r
+ for (int i = 0; i < State.mCharacters.Length; i++)\r
+ {\r
+ State.mCharacters[i].Coordinates = State.Map.GetStartingPositionForPlayer(i + 1);\r
+ }\r
+ State.Entities = State.Map.GetAllEntities(this);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Restart the current level.\r
+ /// </summary>\r
+ public void Reset()\r
+ {\r
+ State.Map.Reset();\r
+ // TODO: Do other stuff to reset everything.\r
+ }\r
+\r
+\r
+ public Game()\r
+ {\r
+ \r
+ }\r