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;
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 mCharacters = new Player[numPlayers];
47 mIsGameOver = new bool[numPlayers];
48 mIsTerminated = new bool[numPlayers];
50 mMouseLocation = new Point[numPlayers];
51 mMouseButton = new bool[numPlayers];
52 mKeysDown = new List<Keys>[numPlayers];
53 for (int i = 0; i < numPlayers; i++) mKeysDown[i] = new List<Keys>();
55 mKeypressCount = new int[numPlayers];
62 /// Should be called by the Game class to advance the state
63 /// to the next frame.
65 /// <param name="inputs">The inputs that occurred to be
66 /// applied this coming frame.</param>
67 /// <param name="milliseconds">Milliseconds; used for the checksum.</param>
68 public void AdvanceFrame(NextInputs inputs, long milliseconds)
71 mElapsedTime += milliseconds;
73 for (int player = 0; player < NumberOfPlayers; player++)
75 if (inputs.IsMousePressedChanged[player])
77 mMouseButton[player] = inputs.MousePressed[player];
80 if (inputs.IsMouseLocationChanged[player])
82 mMouseLocation[player] = inputs.MouseLocation[player];
85 foreach (Keys k in inputs.KeysPressed[player])
87 if (!mKeysDown[player].Contains(k))
89 mKeysDown[player].Add(k);
90 mKeypressCount[player]++;
94 foreach (Keys k in inputs.KeysReleased[player]) mKeysDown[player].Remove(k);
102 /// Get the mouse location for a player.
104 /// <param name="playerNum">Player Number.</param>
105 /// <returns>Mouse location.</returns>
106 public Point GetMouseLocation(int playerNum)
108 return mMouseLocation[playerNum];
112 /// Get the mouse button state for a player.
114 /// <param name="playerNum">Player number.</param>
115 /// <returns>Mouse button state..</returns>
116 public bool GetMouseButton(int playerNum)
118 return mMouseButton[playerNum];
122 /// Get the keyboard state for a player.
124 /// <param name="playerNum">Player number.</param>
125 /// <returns>Keyboard state.</returns>
126 public List<Keys> GetKeysDown(int playerNum)
128 return mKeysDown[playerNum];
134 #region Private Methods
136 // Calculates a checksum for debugging network synchronization issues.
137 long ComputeChecksum()
139 mChecksum += FrameNumber;
140 for (int i = 0; i < NumberOfPlayers; i++)
142 mChecksum = mChecksum + mKeypressCount[i];
143 mChecksum = mChecksum * 3 + (mIsGameOver[i] ? 1 : 2);
144 mChecksum = mChecksum * 3 + (mIsTerminated[i] ? 1 : 2);
145 foreach (Keys k in mKeysDown[i])
146 mChecksum = mChecksum * 257 + (int)k;
147 mChecksum = mChecksum * 25789 + mMouseLocation[i].X * 259 + mMouseLocation[i].Y + 375;
148 mChecksum = mChecksum * 3 + (mMouseButton[i] ? 1 : 2);
151 mChecksum += mElapsedTime;
159 #region Private Variables
161 int mNumberOfPlayers;
162 public Point[] mMouseLocation;
163 public bool[] mMouseButton;
164 public List<Keys>[] mKeysDown;
169 bool[] mIsTerminated;
171 int[] mKeypressCount;
179 /// Container class for all the inputs for a single frame.
181 public class NextInputs
183 public List<Keys>[] KeysPressed;
184 public List<Keys>[] KeysReleased;
185 public Point[] MouseLocation;
186 public bool[] IsMouseLocationChanged;
187 public bool[] MousePressed;
188 public bool[] IsMousePressedChanged;
190 public NextInputs(int numPlayers)
192 KeysPressed = new List<Keys>[numPlayers];
193 KeysReleased = new List<Keys>[numPlayers];
194 IsMouseLocationChanged = new bool[numPlayers];
195 MousePressed = new bool[numPlayers];
196 IsMousePressedChanged = new bool[numPlayers];
197 for (int i = 0; i < numPlayers; i++) KeysPressed[i] = new List<Keys>();
198 for (int i = 0; i < numPlayers; i++) KeysReleased[i] = new List<Keys>();
206 public class Game : IDeterministicGame
208 #region Public Properties
211 /// Get the content manager associated with this game.
213 public ContentManager ContentManager { get { return mContentManager; } }
218 public GameState State;
224 bool[,] grid = State.Map.Grid;
225 foreach (IEntity entity in State.Entities)
227 Point coordinates = entity.Coordinates;
228 if (State.Map.IsCellOpen(coordinates)) grid[coordinates.X, coordinates.Y] = false;
237 #region Public Methods
239 public IEntity GetEntityAtCoordinates(Point point)
241 foreach (IEntity entity in State.Entities)
243 if (entity.Coordinates == point) return entity;
248 public Player GetPlayerAtCoordinates(Point point)
250 foreach (Player player in State.mCharacters)
252 if (player != null && player.Coordinates == point) return player;
257 public bool IsCellOpen(Point point)
259 if (!State.Map.IsCellOpen(point)) return false;
260 if (GetEntityAtCoordinates(point) != null) return false;
269 /// This method should be called whenever the players want to move to a new map.
270 /// Not implemented yet. Need some way to get next map.
272 public void startNewMap()
274 //TODO somehow get next map
275 State.Entities.Clear();
276 //State.Map = State.Map.getNextMap();
277 for (int i = 0; i < State.mCharacters.Length; i++)
279 State.mCharacters[i].Coordinates = State.Map.GetStartingPositionForPlayer(i + 1);
281 State.Entities = State.Map.GetAllEntities(this);
283 public void LoadContent(ContentManager contentManager)
285 mContentManager = contentManager;
286 menu = mContentManager.Load<SpriteFont>("menuFont");
290 public void UnloadContent()
294 private int GetPlayerNumber(Object playerIdentifier)
296 for (int i = 0; i < mPlayerIdentifiers.Length; i++)
298 if (mPlayerIdentifiers[i] == playerIdentifier) return i;
300 throw new Exception("Illegal player identifier" + playerIdentifier);
303 public Vector2 PreferredScreenSize
305 get { return new Vector2(800, 600); }
308 public int MinimumSupportedPlayers
313 public int MaximumSupportedPlayers
318 public void ResetGame(object[] playerIdentifiers, object thisPlayer)
320 int numPlayers = playerIdentifiers.Count();
322 mPlayerIdentifiers = new object[numPlayers];
323 for (int i = 0; i < numPlayers; i++) mPlayerIdentifiers[i] = playerIdentifiers[i];
325 mThisPlayerID = GetPlayerNumber(thisPlayer);
327 State = new GameState(numPlayers);
328 mInputs = new NextInputs(numPlayers);
329 State.mDisplay = new Display(this);
330 State.mDisplay.LoadContent(mContentManager);
332 Texture2D mapTiles = mContentManager.Load<Texture2D>("graphics/wallAndFloorTilesNoEdgeScale");
333 Tilemap tilemap = new Tilemap(mapTiles, 10, 7);
334 tilemap.SetTile(' ', new Point(4, 5));
335 tilemap.SetTile('`', new Point(0, 1));
336 tilemap.SetTile('~', new Point(1, 1));
337 tilemap.SetTile('!', new Point(3, 1));
338 tilemap.SetTile('@', new Point(4, 1));
339 tilemap.SetTile('#', new Point(5, 1));
340 tilemap.SetTile('$', new Point(6, 1));
341 tilemap.SetTile('%', new Point(8, 1));
342 tilemap.SetTile('^', new Point(9, 1));
343 tilemap.SetTile('&', new Point(0, 2));
344 tilemap.SetTile('=', new Point(1, 2));
345 tilemap.SetTile('*', new Point(2, 2));
346 tilemap.SetTile('(', new Point(4, 2));
347 tilemap.SetTile(')', new Point(0, 3));
348 tilemap.SetTile('_', new Point(2, 3));
349 tilemap.SetTile('-', new Point(9, 3));
350 tilemap.SetTile(',', new Point(1, 4));
351 tilemap.SetTile('+', new Point(2, 4));
352 tilemap.SetTile('[', new Point(3, 4));
353 tilemap.SetTile(']', new Point(4, 4));
354 tilemap.SetTile('{', new Point(5, 4));
355 tilemap.SetTile('}', new Point(6, 4));
356 tilemap.SetTile('\\', new Point(8, 4));
357 tilemap.SetTile('|', new Point(9, 4));
358 tilemap.SetTile(';', new Point(0, 5));
359 tilemap.SetTile(':', new Point(1, 5));
360 tilemap.SetTile('\'', new Point(2, 5));
361 tilemap.SetTile('"', new Point(3, 5));
362 tilemap.SetTile('.', new Point(5, 5));
363 tilemap.SetTile('<', new Point(6, 5));
364 tilemap.SetTile('>', new Point(7, 5));
365 tilemap.SetTile('/', new Point(8, 5));
366 tilemap.SetTile('?', new Point(9, 5));
368 State.Map = mContentManager.Load<Map>("Maps/level1");
369 State.Map.Tilemap = tilemap;
370 State.Entities = State.Map.GetAllEntities(this);
372 State.AIData = new AI(this);
376 for (int i = 0; i < PlayerIdentifiers.Length; i++)
378 Human player = new Human(mMap, "");
379 mPlayers.Add(player);
380 mDisplay.AddCharacters(player);
381 mPlayers.Add(player);
382 mDisplay.AddCharacters(player);
384 this.playerIdentifiers = PlayerIdentifiers;
385 for (int i = 0; i < mPlayers.Count; i++)
387 Point starting = mMap.GetStartingPositionForPlayer(i + 1);
388 mPlayers[i].Spawn(new Vector2(starting.X, starting.Y));
393 public long CurrentFrameNumber
395 get { return State.FrameNumber; }
398 public long CurrentChecksum
403 public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed)
405 //code from Prof Jensen's TestHarness
406 int player = GetPlayerNumber(playerIdentifier);
408 if (isKeyPressed && !mInputs.KeysPressed[player].Contains(key))
409 mInputs.KeysPressed[player].Add(key);
411 if (!isKeyPressed && !mInputs.KeysReleased[player].Contains(key))
412 mInputs.KeysReleased[player].Add(key);
416 public void ApplyMouseLocationInput(object playerIdentifier, int x, int y)
421 public void ApplyMouseButtonInput(object playerIdentifier, bool isButtonPressed)
426 public bool IsGameOver(object playerIdentifier)
431 public bool IsTerminated(object playerIdentifier)
436 public long Update(TimeSpan elapsedTime)
438 State.AdvanceFrame(mInputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.
439 State.mDisplay.Update(elapsedTime, mThisPlayerID);
440 State.Entities.ForEach(delegate(IEntity e) { e.Update(elapsedTime); });
441 mInputs = new NextInputs(State.NumberOfPlayers); // Start with inputs cleared on the next frame.
442 //mDisplay.Update(elapsedTime);
443 return State.FrameNumber;
447 public long Draw(SpriteBatch spriteBatch)
449 bool allCharactersSelected = true;
450 for (int i = 0; i < State.NumberOfPlayers; i++)
452 //If player has not selected a player yet let them select one.
453 if (State.mCharacters[i] == null)
455 allCharactersSelected = false;
456 if (State.GetKeysDown(i).Contains(Keys.M))
458 State.mCharacters[i] = new Melee(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
459 State.mCharacters[i].LoadContent(mContentManager);
461 else if (State.GetKeysDown(i).Contains(Keys.R))
463 State.mCharacters[i] = new Ranged(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
464 State.mCharacters[i].LoadContent(mContentManager);
468 if (allCharactersSelected)
471 State.mDisplay.Draw(spriteBatch);
475 spriteBatch.GraphicsDevice.Clear(Color.Black);
476 spriteBatch.DrawString(menu, "Press R to select a Ranged Character and M to select a Melee Character", new Vector2(30, 30), Color.RosyBrown);
478 return CurrentFrameNumber;
484 #region Private Variables
488 ContentManager mContentManager;
491 Object[] mPlayerIdentifiers;