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 Player[] mCharacters = new Player[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
235 public bool IsCellOpen(Point point)
237 if (!State.Map.IsCellOpen(point)) return false;
238 foreach (IEntity entity in State.Entities)
240 if (entity.Coordinates == point) return false;
250 /// This method should be called whenever the players want to move to a new map.
251 /// Not implemented yet. Need some way to get next map.
253 public void startNewMap()
255 //TODO somehow get next map
256 State.Entities.Clear();
257 //State.Map = State.Map.getNextMap();
258 for (int i = 0; i < State.mCharacters.Length; i++)
260 State.mCharacters[i].Coordinates = State.Map.GetStartingPositionForPlayer(i + 1);
262 State.Entities = State.Map.GetAllEntities();
264 public void LoadContent(ContentManager contentManager)
266 mContentManager = contentManager;
267 menu = mContentManager.Load<SpriteFont>("menuFont");
271 public void UnloadContent()
275 private int GetPlayerNumber(Object playerIdentifier)
277 for (int i = 0; i < mPlayerIdentifiers.Length; i++)
279 if (mPlayerIdentifiers[i] == playerIdentifier) return i;
281 throw new Exception("Illegal player identifier" + playerIdentifier);
284 public Vector2 PreferredScreenSize
286 get { return new Vector2(800, 600); }
289 public int MinimumSupportedPlayers
294 public int MaximumSupportedPlayers
299 public void ResetGame(object[] playerIdentifiers, object thisPlayer)
301 int numPlayers = playerIdentifiers.Count();
303 mPlayerIdentifiers = new object[numPlayers];
304 for (int i = 0; i < numPlayers; i++) mPlayerIdentifiers[i] = playerIdentifiers[i];
306 mThisPlayerID = GetPlayerNumber(thisPlayer);
308 State = new GameState(numPlayers);
309 mInputs = new NextInputs(numPlayers);
310 State.mDisplay = new Display(this);
311 State.mDisplay.LoadContent(mContentManager);
313 State.Map = mContentManager.Load<Map>("Maps/stable");
314 State.Map.Game = this;
315 State.Entities = State.Map.GetAllEntities();
316 Map.DefaultTile = mContentManager.Load<Texture2D>("default");
320 for (int i = 0; i < PlayerIdentifiers.Length; i++)
322 Human player = new Human(mMap, "");
323 mPlayers.Add(player);
324 mDisplay.AddCharacters(player);
325 mPlayers.Add(player);
326 mDisplay.AddCharacters(player);
328 this.playerIdentifiers = PlayerIdentifiers;
329 for (int i = 0; i < mPlayers.Count; i++)
331 Point starting = mMap.GetStartingPositionForPlayer(i + 1);
332 mPlayers[i].Spawn(new Vector2(starting.X, starting.Y));
337 public long CurrentFrameNumber
339 get { return State.FrameNumber; }
342 public long CurrentChecksum
347 public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed)
349 //code from Prof Jensen's TestHarness
350 int player = GetPlayerNumber(playerIdentifier);
352 if (isKeyPressed && !mInputs.KeysPressed[player].Contains(key))
353 mInputs.KeysPressed[player].Add(key);
355 if (!isKeyPressed && !mInputs.KeysReleased[player].Contains(key))
356 mInputs.KeysReleased[player].Add(key);
360 public void ApplyMouseLocationInput(object playerIdentifier, int x, int y)
365 public void ApplyMouseButtonInput(object playerIdentifier, bool isButtonPressed)
370 public bool IsGameOver(object playerIdentifier)
375 public bool IsTerminated(object playerIdentifier)
380 public long Update(TimeSpan elapsedTime)
382 State.AdvanceFrame(mInputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.
383 State.mDisplay.Update(elapsedTime, State, mThisPlayerID);
384 State.Entities.ForEach(delegate(IEntity e) { e.Update(elapsedTime); });
385 mInputs = new NextInputs(State.NumberOfPlayers); // Start with inputs cleared on the next frame.
386 //mDisplay.Update(elapsedTime);
387 return State.FrameNumber;
391 public long Draw(SpriteBatch spriteBatch)
393 bool allCharactersSelected = true;
394 for (int i = 0; i < State.NumberOfPlayers; i++)
396 //If player has not selected a player yet let them select one.
397 if (State.mCharacters[i] == null)
399 allCharactersSelected = false;
400 if (State.GetKeysDown(i).Contains(Keys.M))
402 State.mCharacters[i] = new Melee(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
403 State.mCharacters[i].LoadContent(mContentManager);
405 else if (State.GetKeysDown(i).Contains(Keys.R))
407 State.mCharacters[i] = new Ranged(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
408 State.mCharacters[i].LoadContent(mContentManager);
412 if (allCharactersSelected)
415 State.mDisplay.Draw(spriteBatch);
419 spriteBatch.GraphicsDevice.Clear(Color.Black);
420 spriteBatch.DrawString(menu, "Press R to select a Ranged Character and M to select a Melee Character", new Vector2(30, 30), Color.RosyBrown);
422 return CurrentFrameNumber;
428 #region Private Variables
432 ContentManager mContentManager;
435 Object[] mPlayerIdentifiers;