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 List<Projectile> mProjectiles = new List<Projectile>();
28 public Player[] mCharacters = new Player[4];
29 public Display mDisplay;
34 #region Public Methods
37 /// Construct a game state container with the number of players.
39 /// <param name="numPlayers">Number of players.</param>
40 public GameState(int numPlayers)
42 mNumberOfPlayers = numPlayers;
45 mIsGameOver = new bool[numPlayers];
46 mIsTerminated = new bool[numPlayers];
48 mMouseLocation = new Point[numPlayers];
49 mMouseButton = new bool[numPlayers];
50 mKeysDown = new List<Keys>[numPlayers];
51 for (int i = 0; i < numPlayers; i++) mKeysDown[i] = new List<Keys>();
53 mKeypressCount = new int[numPlayers];
60 /// Should be called by the Game class to advance the state
61 /// to the next frame.
63 /// <param name="inputs">The inputs that occurred to be
64 /// applied this coming frame.</param>
65 /// <param name="milliseconds">Milliseconds; used for the checksum.</param>
66 public void AdvanceFrame(NextInputs inputs, long milliseconds)
69 mElapsedTime += milliseconds;
71 for (int player = 0; player < NumberOfPlayers; player++)
73 if (inputs.IsMousePressedChanged[player])
75 mMouseButton[player] = inputs.MousePressed[player];
78 if (inputs.IsMouseLocationChanged[player])
80 mMouseLocation[player] = inputs.MouseLocation[player];
83 foreach (Keys k in inputs.KeysPressed[player])
85 if (!mKeysDown[player].Contains(k))
87 mKeysDown[player].Add(k);
88 mKeypressCount[player]++;
92 foreach (Keys k in inputs.KeysReleased[player]) mKeysDown[player].Remove(k);
100 /// Get the mouse location for a player.
102 /// <param name="playerNum">Player Number.</param>
103 /// <returns>Mouse location.</returns>
104 public Point GetMouseLocation(int playerNum)
106 return mMouseLocation[playerNum];
110 /// Get the mouse button state for a player.
112 /// <param name="playerNum">Player number.</param>
113 /// <returns>Mouse button state..</returns>
114 public bool GetMouseButton(int playerNum)
116 return mMouseButton[playerNum];
120 /// Get the keyboard state for a player.
122 /// <param name="playerNum">Player number.</param>
123 /// <returns>Keyboard state.</returns>
124 public List<Keys> GetKeysDown(int playerNum)
126 return mKeysDown[playerNum];
132 #region Private Methods
134 // Calculates a checksum for debugging network synchronization issues.
135 long ComputeChecksum()
137 mChecksum += FrameNumber;
138 for (int i = 0; i < NumberOfPlayers; i++)
140 mChecksum = mChecksum + mKeypressCount[i];
141 mChecksum = mChecksum * 3 + (mIsGameOver[i] ? 1 : 2);
142 mChecksum = mChecksum * 3 + (mIsTerminated[i] ? 1 : 2);
143 foreach (Keys k in mKeysDown[i])
144 mChecksum = mChecksum * 257 + (int)k;
145 mChecksum = mChecksum * 25789 + mMouseLocation[i].X * 259 + mMouseLocation[i].Y + 375;
146 mChecksum = mChecksum * 3 + (mMouseButton[i] ? 1 : 2);
149 mChecksum += mElapsedTime;
157 #region Private Variables
159 int mNumberOfPlayers;
160 public Point[] mMouseLocation;
161 public bool[] mMouseButton;
162 public List<Keys>[] mKeysDown;
167 bool[] mIsTerminated;
169 int[] mKeypressCount;
177 /// Container class for all the inputs for a single frame.
179 public class NextInputs
181 public List<Keys>[] KeysPressed;
182 public List<Keys>[] KeysReleased;
183 public Point[] MouseLocation;
184 public bool[] IsMouseLocationChanged;
185 public bool[] MousePressed;
186 public bool[] IsMousePressedChanged;
188 public NextInputs(int numPlayers)
190 KeysPressed = new List<Keys>[numPlayers];
191 KeysReleased = new List<Keys>[numPlayers];
192 IsMouseLocationChanged = new bool[numPlayers];
193 MousePressed = new bool[numPlayers];
194 IsMousePressedChanged = new bool[numPlayers];
195 for (int i = 0; i < numPlayers; i++) KeysPressed[i] = new List<Keys>();
196 for (int i = 0; i < numPlayers; i++) KeysReleased[i] = new List<Keys>();
204 public class Game : IDeterministicGame
206 #region Public Properties
209 /// Get the content manager associated with this game.
211 public ContentManager ContentManager { get { return mContentManager; } }
216 public GameState State;
222 bool[,] grid = State.Map.Grid;
223 foreach (IEntity entity in State.Entities)
225 Point coordinates = entity.Coordinates;
226 grid[coordinates.X, coordinates.Y] = true;
235 #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;
251 /// This method should be called whenever the players want to move to a new map.
252 /// Not implemented yet. Need some way to get next map.
254 public void startNewMap()
256 //TODO somehow get next map
257 State.Entities.Clear();
258 //State.Map = State.Map.getNextMap();
259 for (int i = 0; i < State.mCharacters.Length; i++)
261 State.mCharacters[i].Coordinates = State.Map.GetStartingPositionForPlayer(i + 1);
263 State.Entities = State.Map.GetAllEntities(this);
265 public void LoadContent(ContentManager contentManager)
267 mContentManager = contentManager;
268 menu = mContentManager.Load<SpriteFont>("menuFont");
272 public void UnloadContent()
276 private int GetPlayerNumber(Object playerIdentifier)
278 for (int i = 0; i < mPlayerIdentifiers.Length; i++)
280 if (mPlayerIdentifiers[i] == playerIdentifier) return i;
282 throw new Exception("Illegal player identifier" + playerIdentifier);
285 public Vector2 PreferredScreenSize
287 get { return new Vector2(800, 600); }
290 public int MinimumSupportedPlayers
295 public int MaximumSupportedPlayers
300 public void ResetGame(object[] playerIdentifiers, object thisPlayer)
302 int numPlayers = playerIdentifiers.Count();
304 mPlayerIdentifiers = new object[numPlayers];
305 for (int i = 0; i < numPlayers; i++) mPlayerIdentifiers[i] = playerIdentifiers[i];
307 mThisPlayerID = GetPlayerNumber(thisPlayer);
309 State = new GameState(numPlayers);
310 mInputs = new NextInputs(numPlayers);
311 State.mDisplay = new Display(this);
312 State.mDisplay.LoadContent(mContentManager);
314 State.Map = mContentManager.Load<Map>("Maps/stable");
315 State.Entities = State.Map.GetAllEntities(this);
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, 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;