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();
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.Map.Game = this;
316 State.Entities = State.Map.GetAllEntities();
317 Map.DefaultTile = mContentManager.Load<Texture2D>("default");
321 for (int i = 0; i < PlayerIdentifiers.Length; i++)
323 Human player = new Human(mMap, "");
324 mPlayers.Add(player);
325 mDisplay.AddCharacters(player);
326 mPlayers.Add(player);
327 mDisplay.AddCharacters(player);
329 this.playerIdentifiers = PlayerIdentifiers;
330 for (int i = 0; i < mPlayers.Count; i++)
332 Point starting = mMap.GetStartingPositionForPlayer(i + 1);
333 mPlayers[i].Spawn(new Vector2(starting.X, starting.Y));
338 public long CurrentFrameNumber
340 get { return State.FrameNumber; }
343 public long CurrentChecksum
348 public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed)
350 //code from Prof Jensen's TestHarness
351 int player = GetPlayerNumber(playerIdentifier);
353 if (isKeyPressed && !mInputs.KeysPressed[player].Contains(key))
354 mInputs.KeysPressed[player].Add(key);
356 if (!isKeyPressed && !mInputs.KeysReleased[player].Contains(key))
357 mInputs.KeysReleased[player].Add(key);
361 public void ApplyMouseLocationInput(object playerIdentifier, int x, int y)
366 public void ApplyMouseButtonInput(object playerIdentifier, bool isButtonPressed)
371 public bool IsGameOver(object playerIdentifier)
376 public bool IsTerminated(object playerIdentifier)
381 public long Update(TimeSpan elapsedTime)
383 State.AdvanceFrame(mInputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.
384 State.mDisplay.Update(elapsedTime, mThisPlayerID);
385 State.Entities.ForEach(delegate(IEntity e) { e.Update(elapsedTime); });
386 mInputs = new NextInputs(State.NumberOfPlayers); // Start with inputs cleared on the next frame.
387 //mDisplay.Update(elapsedTime);
388 return State.FrameNumber;
392 public long Draw(SpriteBatch spriteBatch)
394 bool allCharactersSelected = true;
395 for (int i = 0; i < State.NumberOfPlayers; i++)
397 //If player has not selected a player yet let them select one.
398 if (State.mCharacters[i] == null)
400 allCharactersSelected = false;
401 if (State.GetKeysDown(i).Contains(Keys.M))
403 State.mCharacters[i] = new Melee(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
404 State.mCharacters[i].LoadContent(mContentManager);
406 else if (State.GetKeysDown(i).Contains(Keys.R))
408 State.mCharacters[i] = new Ranged(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
409 State.mCharacters[i].LoadContent(mContentManager);
413 if (allCharactersSelected)
416 State.mDisplay.Draw(spriteBatch);
420 spriteBatch.GraphicsDevice.Clear(Color.Black);
421 spriteBatch.DrawString(menu, "Press R to select a Ranged Character and M to select a Melee Character", new Vector2(30, 30), Color.RosyBrown);
423 return CurrentFrameNumber;
429 #region Private Variables
433 ContentManager mContentManager;
436 Object[] mPlayerIdentifiers;