2 using System.Collections.Generic;
5 using Microsoft.Xna.Framework;
6 using Microsoft.Xna.Framework.Content;
7 using Microsoft.Xna.Framework.Graphics;
8 using Microsoft.Xna.Framework.Input;
13 /// Container class for the whole state of the game.
15 public class GameState
17 #region Public Properties
19 public long FrameNumber { get { return mFrameNumber; } }
21 public long Checksum { get { return mChecksum; } }
23 public int NumberOfPlayers { get { return mNumberOfPlayers; } }
26 public List<IEntity> Entities = new List<IEntity>();
27 public IPlayer[] mCharacters = new IPlayer[4];
28 public Display mDisplay;
33 #region Public Methods
36 /// Construct a game state container with the number of players.
38 /// <param name="numPlayers">Number of players.</param>
39 public GameState(int numPlayers)
41 mNumberOfPlayers = numPlayers;
44 mIsGameOver = new bool[numPlayers];
45 mIsTerminated = new bool[numPlayers];
47 mMouseLocation = new Point[numPlayers];
48 mMouseButton = new bool[numPlayers];
49 mKeysDown = new List<Keys>[numPlayers];
50 for (int i = 0; i < numPlayers; i++) mKeysDown[i] = new List<Keys>();
52 mKeypressCount = new int[numPlayers];
59 /// Should be called by the Game class to advance the state
60 /// to the next frame.
62 /// <param name="inputs">The inputs that occurred to be
63 /// applied this coming frame.</param>
64 /// <param name="milliseconds">Milliseconds; used for the checksum.</param>
65 public void AdvanceFrame(NextInputs inputs, long milliseconds)
68 mElapsedTime += milliseconds;
70 for (int player = 0; player < NumberOfPlayers; player++)
72 if (inputs.IsMousePressedChanged[player])
74 mMouseButton[player] = inputs.MousePressed[player];
77 if (inputs.IsMouseLocationChanged[player])
79 mMouseLocation[player] = inputs.MouseLocation[player];
82 foreach (Keys k in inputs.KeysPressed[player])
84 if (!mKeysDown[player].Contains(k))
86 mKeysDown[player].Add(k);
87 mKeypressCount[player]++;
91 foreach (Keys k in inputs.KeysReleased[player]) mKeysDown[player].Remove(k);
99 /// Get the mouse location for a player.
101 /// <param name="playerNum">Player Number.</param>
102 /// <returns>Mouse location.</returns>
103 public Point GetMouseLocation(int playerNum)
105 return mMouseLocation[playerNum];
109 /// Get the mouse button state for a player.
111 /// <param name="playerNum">Player number.</param>
112 /// <returns>Mouse button state..</returns>
113 public bool GetMouseButton(int playerNum)
115 return mMouseButton[playerNum];
119 /// Get the keyboard state for a player.
121 /// <param name="playerNum">Player number.</param>
122 /// <returns>Keyboard state.</returns>
123 public List<Keys> GetKeysDown(int playerNum)
125 return mKeysDown[playerNum];
131 #region Private Methods
133 // Calculates a checksum for debugging network synchronization issues.
134 long ComputeChecksum()
136 mChecksum += FrameNumber;
137 for (int i = 0; i < NumberOfPlayers; i++)
139 mChecksum = mChecksum + mKeypressCount[i];
140 mChecksum = mChecksum * 3 + (mIsGameOver[i] ? 1 : 2);
141 mChecksum = mChecksum * 3 + (mIsTerminated[i] ? 1 : 2);
142 foreach (Keys k in mKeysDown[i])
143 mChecksum = mChecksum * 257 + (int)k;
144 mChecksum = mChecksum * 25789 + mMouseLocation[i].X * 259 + mMouseLocation[i].Y + 375;
145 mChecksum = mChecksum * 3 + (mMouseButton[i] ? 1 : 2);
148 mChecksum += mElapsedTime;
156 #region Private Variables
158 int mNumberOfPlayers;
159 public Point[] mMouseLocation;
160 public bool[] mMouseButton;
161 public List<Keys>[] mKeysDown;
166 bool[] mIsTerminated;
168 int[] mKeypressCount;
176 /// Container class for all the inputs for a single frame.
178 public class NextInputs
180 public List<Keys>[] KeysPressed;
181 public List<Keys>[] KeysReleased;
182 public Point[] MouseLocation;
183 public bool[] IsMouseLocationChanged;
184 public bool[] MousePressed;
185 public bool[] IsMousePressedChanged;
187 public NextInputs(int numPlayers)
189 KeysPressed = new List<Keys>[numPlayers];
190 KeysReleased = new List<Keys>[numPlayers];
191 IsMouseLocationChanged = new bool[numPlayers];
192 MousePressed = new bool[numPlayers];
193 IsMousePressedChanged = new bool[numPlayers];
194 for (int i = 0; i < numPlayers; i++) KeysPressed[i] = new List<Keys>();
195 for (int i = 0; i < numPlayers; i++) KeysReleased[i] = new List<Keys>();
203 public class Game : IDeterministicGame
205 #region Public Properties
208 /// Get the content manager associated with this game.
210 public ContentManager ContentManager { get { return mContentManager; } }
215 public GameState State;
221 bool[,] grid = State.Map.Grid;
222 foreach (IEntity entity in State.Entities)
224 Point coordinates = entity.Coordinates;
225 grid[coordinates.X, coordinates.Y] = true;
234 #region Public Methods
236 public bool IsCellOpen(Point point)
238 if (!State.Map.IsCellOpen(point)) return false;
239 foreach (IEntity entity in State.Entities)
241 if (entity.Coordinates == point) return false;
250 public void LoadContent(ContentManager contentManager)
252 mContentManager = contentManager;
253 menu = mContentManager.Load<SpriteFont>("menuFont");
257 public void UnloadContent()
261 private int GetPlayerNumber(Object playerIdentifier)
263 for (int i = 0; i < mPlayerIdentifiers.Length; i++)
265 if (mPlayerIdentifiers[i] == playerIdentifier) return i;
267 throw new Exception("Illegal player identifier" + playerIdentifier);
270 public Vector2 PreferredScreenSize
272 get { return new Vector2(800, 600); }
275 public int MinimumSupportedPlayers
280 public int MaximumSupportedPlayers
285 public void ResetGame(object[] playerIdentifiers, object thisPlayer)
287 int numPlayers = playerIdentifiers.Count();
289 mPlayerIdentifiers = new object[numPlayers];
290 for (int i = 0; i < numPlayers; i++) mPlayerIdentifiers[i] = playerIdentifiers[i];
292 mThisPlayerID = GetPlayerNumber(thisPlayer);
294 State = new GameState(numPlayers);
295 mInputs = new NextInputs(numPlayers);
296 State.mDisplay = new Display(this);
297 State.mDisplay.LoadContent(mContentManager);
299 State.Map = mContentManager.Load<Map>("Maps/stable");
300 State.Map.Game = this;
301 State.Entities = State.Map.GetAllEntities();
302 Map.DefaultTile = mContentManager.Load<Texture2D>("default");
306 for (int i = 0; i < PlayerIdentifiers.Length; i++)
308 Human player = new Human(mMap, "");
309 mPlayers.Add(player);
310 mDisplay.AddCharacters(player);
311 mPlayers.Add(player);
312 mDisplay.AddCharacters(player);
314 this.playerIdentifiers = PlayerIdentifiers;
315 for (int i = 0; i < mPlayers.Count; i++)
317 Point starting = mMap.GetStartingPositionForPlayer(i + 1);
318 mPlayers[i].Spawn(new Vector2(starting.X, starting.Y));
323 public long CurrentFrameNumber
325 get { return State.FrameNumber; }
328 public long CurrentChecksum
333 public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed)
335 //code from Prof Jensen's TestHarness
336 int player = GetPlayerNumber(playerIdentifier);
338 if (isKeyPressed && !mInputs.KeysPressed[player].Contains(key))
339 mInputs.KeysPressed[player].Add(key);
341 if (!isKeyPressed && !mInputs.KeysReleased[player].Contains(key))
342 mInputs.KeysReleased[player].Add(key);
346 public void ApplyMouseLocationInput(object playerIdentifier, int x, int y)
351 public void ApplyMouseButtonInput(object playerIdentifier, bool isButtonPressed)
356 public bool IsGameOver(object playerIdentifier)
361 public bool IsTerminated(object playerIdentifier)
366 public long Update(TimeSpan elapsedTime)
368 State.AdvanceFrame(mInputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.
369 State.mDisplay.Update(elapsedTime, State, mThisPlayerID);
370 State.Entities.ForEach(delegate(IEntity e) { e.Update(elapsedTime); });
371 mInputs = new NextInputs(State.NumberOfPlayers); // Start with inputs cleared on the next frame.
372 //mDisplay.Update(elapsedTime);
373 return State.FrameNumber;
377 public long Draw(SpriteBatch spriteBatch)
379 bool allCharactersSelected = true;
380 for (int i = 0; i < State.NumberOfPlayers; i++)
382 //If player has not selected a player yet let them select one.
383 if (State.mCharacters[i] == null)
385 allCharactersSelected = false;
386 if (State.GetKeysDown(i).Contains(Keys.Enter))
388 State.mCharacters[i] = new Human(this, "", State.Map.GetStartingPositionForPlayer(i + 1));
389 State.mCharacters[i].LoadContent(mContentManager);
393 if (allCharactersSelected)
396 State.mDisplay.Draw(spriteBatch);
400 spriteBatch.GraphicsDevice.Clear(Color.Black);
401 spriteBatch.DrawString(menu, "Press Enter To Select A Character", new Vector2(30, 30), Color.RosyBrown);
403 return CurrentFrameNumber;
409 #region Private Variables
413 ContentManager mContentManager;
416 Object[] mPlayerIdentifiers;