]> Dogcows Code - chaz/carfire/blob - CarFire/CarFire/CarFire/Game.cs
Fixed path finder thrown exception when finding a path to the cell you are already at.
[chaz/carfire] / CarFire / CarFire / CarFire / Game.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using Microsoft.Xna.Framework;
6 using Microsoft.Xna.Framework.Content;
7 using Microsoft.Xna.Framework.Graphics;
8 using Microsoft.Xna.Framework.Input;
9
10 namespace CarFire
11 {
12 /// <summary>
13 /// Container class for the whole state of the game.
14 /// </summary>
15 public class GameState
16 {
17 #region Public Properties
18
19 public long FrameNumber { get { return mFrameNumber; } }
20
21 public long Checksum { get { return mChecksum; } }
22
23 public int NumberOfPlayers { get { return mNumberOfPlayers; } }
24
25 public Map Map;
26 public List<IEntity> Entities = new List<IEntity>();
27 public List<Projectile> mProjectiles = new List<Projectile>();
28 public Player[] mCharacters;
29 public Display mDisplay;
30
31 #endregion
32
33
34 #region Public Methods
35
36 /// <summary>
37 /// Construct a game state container with the number of players.
38 /// </summary>
39 /// <param name="numPlayers">Number of players.</param>
40 public GameState(int numPlayers)
41 {
42 mNumberOfPlayers = numPlayers;
43 mFrameNumber = 0;
44
45 mCharacters = new Player[numPlayers];
46
47 mIsGameOver = new bool[numPlayers];
48 mIsTerminated = new bool[numPlayers];
49
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>();
54
55 mKeypressCount = new int[numPlayers];
56 mElapsedTime = 0;
57 mChecksum = 0;
58 }
59
60
61 /// <summary>
62 /// Should be called by the Game class to advance the state
63 /// to the next frame.
64 /// </summary>
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)
69 {
70 mFrameNumber++;
71 mElapsedTime += milliseconds;
72
73 for (int player = 0; player < NumberOfPlayers; player++)
74 {
75 if (inputs.IsMousePressedChanged[player])
76 {
77 mMouseButton[player] = inputs.MousePressed[player];
78 }
79
80 if (inputs.IsMouseLocationChanged[player])
81 {
82 mMouseLocation[player] = inputs.MouseLocation[player];
83 }
84
85 foreach (Keys k in inputs.KeysPressed[player])
86 {
87 if (!mKeysDown[player].Contains(k))
88 {
89 mKeysDown[player].Add(k);
90 mKeypressCount[player]++;
91 }
92 }
93
94 foreach (Keys k in inputs.KeysReleased[player]) mKeysDown[player].Remove(k);
95 }
96
97 ComputeChecksum();
98 }
99
100
101 /// <summary>
102 /// Get the mouse location for a player.
103 /// </summary>
104 /// <param name="playerNum">Player Number.</param>
105 /// <returns>Mouse location.</returns>
106 public Point GetMouseLocation(int playerNum)
107 {
108 return mMouseLocation[playerNum];
109 }
110
111 /// <summary>
112 /// Get the mouse button state for a player.
113 /// </summary>
114 /// <param name="playerNum">Player number.</param>
115 /// <returns>Mouse button state..</returns>
116 public bool GetMouseButton(int playerNum)
117 {
118 return mMouseButton[playerNum];
119 }
120
121 /// <summary>
122 /// Get the keyboard state for a player.
123 /// </summary>
124 /// <param name="playerNum">Player number.</param>
125 /// <returns>Keyboard state.</returns>
126 public List<Keys> GetKeysDown(int playerNum)
127 {
128 return mKeysDown[playerNum];
129 }
130
131 #endregion
132
133
134 #region Private Methods
135
136 // Calculates a checksum for debugging network synchronization issues.
137 long ComputeChecksum()
138 {
139 mChecksum += FrameNumber;
140 for (int i = 0; i < NumberOfPlayers; i++)
141 {
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);
149
150 }
151 mChecksum += mElapsedTime;
152
153 return mChecksum;
154 }
155
156 #endregion
157
158
159 #region Private Variables
160
161 int mNumberOfPlayers;
162 public Point[] mMouseLocation;
163 public bool[] mMouseButton;
164 public List<Keys>[] mKeysDown;
165
166 long mFrameNumber;
167
168 bool[] mIsGameOver;
169 bool[] mIsTerminated;
170
171 int[] mKeypressCount;
172 long mElapsedTime;
173 long mChecksum;
174
175 #endregion
176 }
177
178 /// <summary>
179 /// Container class for all the inputs for a single frame.
180 /// </summary>
181 public class NextInputs
182 {
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;
189
190 public NextInputs(int numPlayers)
191 {
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>();
199 }
200 }
201
202
203 /// <summary>
204 /// The big kahuna.
205 /// </summary>
206 public class Game : IDeterministicGame
207 {
208 #region Public Properties
209
210 /// <summary>
211 /// Get the content manager associated with this game.
212 /// </summary>
213 public ContentManager ContentManager { get { return mContentManager; } }
214
215 /// <summary>
216 /// Get the state.
217 /// </summary>
218 public GameState State;
219
220 public bool[,] Grid
221 {
222 get
223 {
224 bool[,] grid = State.Map.Grid;
225 foreach (IEntity entity in State.Entities)
226 {
227 Point coordinates = entity.Coordinates;
228 if (State.Map.IsCellOpen(coordinates)) grid[coordinates.X, coordinates.Y] = false;
229 }
230 return grid;
231 }
232 }
233
234 #endregion
235
236
237 #region Public Methods
238
239 public IEntity GetEntityAtCoordinates(Point point)
240 {
241 foreach (IEntity entity in State.Entities)
242 {
243 if (entity.Coordinates == point) return entity;
244 }
245 return null;
246 }
247
248 public Player GetPlayerAtCoordinates(Point point)
249 {
250 foreach (Player player in State.mCharacters)
251 {
252 if (player != null && player.Coordinates == point) return player;
253 }
254 return null;
255 }
256
257 public bool IsCellOpen(Point point)
258 {
259 if (!State.Map.IsCellOpen(point)) return false;
260 if (GetEntityAtCoordinates(point) != null) return false;
261 return true;
262 }
263
264 public Game()
265 {
266
267 }
268 /// <summary>
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.
271 /// </summary>
272 public void startNewMap()
273 {
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++)
278 {
279 State.mCharacters[i].Coordinates = State.Map.GetStartingPositionForPlayer(i + 1);
280 }
281 State.Entities = State.Map.GetAllEntities(this);
282 }
283 public void LoadContent(ContentManager contentManager)
284 {
285 mContentManager = contentManager;
286 menu = mContentManager.Load<SpriteFont>("menuFont");
287
288 }
289
290 public void UnloadContent()
291 {
292 }
293
294 private int GetPlayerNumber(Object playerIdentifier)
295 {
296 for (int i = 0; i < mPlayerIdentifiers.Length; i++)
297 {
298 if (mPlayerIdentifiers[i] == playerIdentifier) return i;
299 }
300 throw new Exception("Illegal player identifier" + playerIdentifier);
301 }
302
303 public Vector2 PreferredScreenSize
304 {
305 get { return new Vector2(800, 600); }
306 }
307
308 public int MinimumSupportedPlayers
309 {
310 get { return 1; }
311 }
312
313 public int MaximumSupportedPlayers
314 {
315 get { return 4; }
316 }
317
318 public void ResetGame(object[] playerIdentifiers, object thisPlayer)
319 {
320 int numPlayers = playerIdentifiers.Count();
321
322 mPlayerIdentifiers = new object[numPlayers];
323 for (int i = 0; i < numPlayers; i++) mPlayerIdentifiers[i] = playerIdentifiers[i];
324
325 mThisPlayerID = GetPlayerNumber(thisPlayer);
326
327 State = new GameState(numPlayers);
328 mInputs = new NextInputs(numPlayers);
329 State.mDisplay = new Display(this);
330 State.mDisplay.LoadContent(mContentManager);
331
332 State.Map = mContentManager.Load<Map>("Maps/level1");
333 State.Entities = State.Map.GetAllEntities(this);
334 Map.DefaultTile = mContentManager.Load<Texture2D>("default");
335
336 /*
337 mPlayers.Clear();
338 for (int i = 0; i < PlayerIdentifiers.Length; i++)
339 {
340 Human player = new Human(mMap, "");
341 mPlayers.Add(player);
342 mDisplay.AddCharacters(player);
343 mPlayers.Add(player);
344 mDisplay.AddCharacters(player);
345 }
346 this.playerIdentifiers = PlayerIdentifiers;
347 for (int i = 0; i < mPlayers.Count; i++)
348 {
349 Point starting = mMap.GetStartingPositionForPlayer(i + 1);
350 mPlayers[i].Spawn(new Vector2(starting.X, starting.Y));
351 }
352 */
353 }
354
355 public long CurrentFrameNumber
356 {
357 get { return State.FrameNumber; }
358 }
359
360 public long CurrentChecksum
361 {
362 get { return 0; }
363 }
364
365 public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed)
366 {
367 //code from Prof Jensen's TestHarness
368 int player = GetPlayerNumber(playerIdentifier);
369
370 if (isKeyPressed && !mInputs.KeysPressed[player].Contains(key))
371 mInputs.KeysPressed[player].Add(key);
372
373 if (!isKeyPressed && !mInputs.KeysReleased[player].Contains(key))
374 mInputs.KeysReleased[player].Add(key);
375
376 }
377
378 public void ApplyMouseLocationInput(object playerIdentifier, int x, int y)
379 {
380
381 }
382
383 public void ApplyMouseButtonInput(object playerIdentifier, bool isButtonPressed)
384 {
385
386 }
387
388 public bool IsGameOver(object playerIdentifier)
389 {
390 return false;
391 }
392
393 public bool IsTerminated(object playerIdentifier)
394 {
395 return false;
396 }
397
398 public long Update(TimeSpan elapsedTime)
399 {
400 State.AdvanceFrame(mInputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.
401 State.mDisplay.Update(elapsedTime, mThisPlayerID);
402 State.Entities.ForEach(delegate(IEntity e) { e.Update(elapsedTime); });
403 mInputs = new NextInputs(State.NumberOfPlayers); // Start with inputs cleared on the next frame.
404 //mDisplay.Update(elapsedTime);
405 return State.FrameNumber;
406
407 }
408
409 public long Draw(SpriteBatch spriteBatch)
410 {
411 bool allCharactersSelected = true;
412 for (int i = 0; i < State.NumberOfPlayers; i++)
413 {
414 //If player has not selected a player yet let them select one.
415 if (State.mCharacters[i] == null)
416 {
417 allCharactersSelected = false;
418 if (State.GetKeysDown(i).Contains(Keys.M))
419 {
420 State.mCharacters[i] = new Melee(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
421 State.mCharacters[i].LoadContent(mContentManager);
422 }
423 else if (State.GetKeysDown(i).Contains(Keys.R))
424 {
425 State.mCharacters[i] = new Ranged(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
426 State.mCharacters[i].LoadContent(mContentManager);
427 }
428 }
429 }
430 if (allCharactersSelected)
431 {
432
433 State.mDisplay.Draw(spriteBatch);
434 }
435 else
436 {
437 spriteBatch.GraphicsDevice.Clear(Color.Black);
438 spriteBatch.DrawString(menu, "Press R to select a Ranged Character and M to select a Melee Character", new Vector2(30, 30), Color.RosyBrown);
439 }
440 return CurrentFrameNumber;
441 }
442
443 #endregion
444
445
446 #region Private Variables
447
448 SpriteFont menu;
449
450 ContentManager mContentManager;
451 NextInputs mInputs;
452
453 Object[] mPlayerIdentifiers;
454 int mThisPlayerID;
455
456 #endregion
457 }
458 }
This page took 0.052494 seconds and 4 git commands to generate.