]> Dogcows Code - chaz/carfire/blob - CarFire/CarFire/CarFire/Game.cs
Moved a couple lines...
[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 int HitMonsterScore { get { return hitMonsterScore; } }
20 public int KillMonsterScore { get { return killMonsterScore; } }
21
22 public long FrameNumber { get { return mFrameNumber; } }
23
24 public long Checksum { get { return mChecksum; } }
25
26 public int NumberOfPlayers { get { return mNumberOfPlayers; } }
27
28 public Map Map;
29 public List<IEntity> Entities = new List<IEntity>();
30 public List<Projectile> mProjectiles = new List<Projectile>();
31 public Player[] mCharacters;
32 public Display mDisplay;
33 #endregion
34
35
36 #region Public Methods
37
38 /// <summary>
39 /// Construct a game state container with the number of players.
40 /// </summary>
41 /// <param name="numPlayers">Number of players.</param>
42 public GameState(int numPlayers)
43 {
44 mNumberOfPlayers = numPlayers;
45 mFrameNumber = 0;
46
47 mCharacters = new Player[numPlayers];
48
49 mIsGameOver = new bool[numPlayers];
50 mIsTerminated = new bool[numPlayers];
51
52 mMouseLocation = new Point[numPlayers];
53 mMouseButton = new bool[numPlayers];
54 mKeysDown = new List<Keys>[numPlayers];
55 for (int i = 0; i < numPlayers; i++) mKeysDown[i] = new List<Keys>();
56
57 mKeypressCount = new int[numPlayers];
58 mElapsedTime = 0;
59 mChecksum = 0;
60 }
61
62
63 /// <summary>
64 /// Should be called by the Game class to advance the state
65 /// to the next frame.
66 /// </summary>
67 /// <param name="inputs">The inputs that occurred to be
68 /// applied this coming frame.</param>
69 /// <param name="milliseconds">Milliseconds; used for the checksum.</param>
70 public void AdvanceFrame(NextInputs inputs, long milliseconds)
71 {
72 mFrameNumber++;
73 mElapsedTime += milliseconds;
74
75 for (int player = 0; player < NumberOfPlayers; player++)
76 {
77 if (inputs.IsMousePressedChanged[player])
78 {
79 mMouseButton[player] = inputs.MousePressed[player];
80 }
81
82 if (inputs.IsMouseLocationChanged[player])
83 {
84 mMouseLocation[player] = inputs.MouseLocation[player];
85 }
86
87 foreach (Keys k in inputs.KeysPressed[player])
88 {
89 if (!mKeysDown[player].Contains(k))
90 {
91 mKeysDown[player].Add(k);
92 mKeypressCount[player]++;
93 }
94 }
95
96 foreach (Keys k in inputs.KeysReleased[player]) mKeysDown[player].Remove(k);
97 }
98
99 ComputeChecksum();
100 }
101
102
103 /// <summary>
104 /// Get the mouse location for a player.
105 /// </summary>
106 /// <param name="playerNum">Player Number.</param>
107 /// <returns>Mouse location.</returns>
108 public Point GetMouseLocation(int playerNum)
109 {
110 return mMouseLocation[playerNum];
111 }
112
113 /// <summary>
114 /// Get the mouse button state for a player.
115 /// </summary>
116 /// <param name="playerNum">Player number.</param>
117 /// <returns>Mouse button state..</returns>
118 public bool GetMouseButton(int playerNum)
119 {
120 return mMouseButton[playerNum];
121 }
122
123 /// <summary>
124 /// Get the keyboard state for a player.
125 /// </summary>
126 /// <param name="playerNum">Player number.</param>
127 /// <returns>Keyboard state.</returns>
128 public List<Keys> GetKeysDown(int playerNum)
129 {
130 return mKeysDown[playerNum];
131 }
132
133 #endregion
134
135
136 #region Private Methods
137
138 // Calculates a checksum for debugging network synchronization issues.
139 long ComputeChecksum()
140 {
141 mChecksum += FrameNumber;
142 for (int i = 0; i < NumberOfPlayers; i++)
143 {
144 mChecksum = mChecksum + mKeypressCount[i];
145 mChecksum = mChecksum * 3 + (mIsGameOver[i] ? 1 : 2);
146 mChecksum = mChecksum * 3 + (mIsTerminated[i] ? 1 : 2);
147 foreach (Keys k in mKeysDown[i])
148 mChecksum = mChecksum * 257 + (int)k;
149 mChecksum = mChecksum * 25789 + mMouseLocation[i].X * 259 + mMouseLocation[i].Y + 375;
150 mChecksum = mChecksum * 3 + (mMouseButton[i] ? 1 : 2);
151
152 }
153 mChecksum += mElapsedTime;
154
155 return mChecksum;
156 }
157
158 #endregion
159
160
161 #region Private Variables
162 private const int hitMonsterScore = 20;
163 private const int killMonsterScore = 100;
164 int mNumberOfPlayers;
165 public Point[] mMouseLocation;
166 public bool[] mMouseButton;
167 public List<Keys>[] mKeysDown;
168
169 long mFrameNumber;
170
171 bool[] mIsGameOver;
172 bool[] mIsTerminated;
173
174 int[] mKeypressCount;
175 long mElapsedTime;
176 long mChecksum;
177
178 #endregion
179 }
180
181 /// <summary>
182 /// Container class for all the inputs for a single frame.
183 /// </summary>
184 public class NextInputs
185 {
186 public List<Keys>[] KeysPressed;
187 public List<Keys>[] KeysReleased;
188 public Point[] MouseLocation;
189 public bool[] IsMouseLocationChanged;
190 public bool[] MousePressed;
191 public bool[] IsMousePressedChanged;
192
193 public NextInputs(int numPlayers)
194 {
195 KeysPressed = new List<Keys>[numPlayers];
196 KeysReleased = new List<Keys>[numPlayers];
197 IsMouseLocationChanged = new bool[numPlayers];
198 MousePressed = new bool[numPlayers];
199 IsMousePressedChanged = new bool[numPlayers];
200 for (int i = 0; i < numPlayers; i++) KeysPressed[i] = new List<Keys>();
201 for (int i = 0; i < numPlayers; i++) KeysReleased[i] = new List<Keys>();
202 }
203 }
204
205
206 /// <summary>
207 /// The big kahuna.
208 /// </summary>
209 public class Game : IDeterministicGame
210 {
211 #region Public Properties
212
213 /// <summary>
214 /// Get the content manager associated with this game.
215 /// </summary>
216 public ContentManager ContentManager { get { return mContentManager; } }
217
218 /// <summary>
219 /// Get the state.
220 /// </summary>
221 public GameState State;
222
223 public bool[,] Grid
224 {
225 get
226 {
227 bool[,] grid = (bool[,])State.Map.Grid.Clone();
228 foreach (IEntity entity in State.Entities)
229 {
230 Point coordinates = entity.Coordinates;
231 grid[coordinates.X, coordinates.Y] = false;
232 }
233 foreach (Player player in State.mCharacters)
234 {
235 if (player == null) continue;
236 Point coordinates = player.Coordinates;
237 grid[coordinates.X, coordinates.Y] = false;
238 }
239 return grid;
240 }
241 }
242
243 #endregion
244
245
246 #region Public Methods
247
248 /// <summary>
249 /// Get an entity at a certain place on the map.
250 /// </summary>
251 /// <param name="point">The coordinates.</param>
252 /// <returns>The entity, or null if none is at that location.</returns>
253 public IEntity GetEntityAtCoordinates(Point point)
254 {
255 foreach (IEntity entity in State.Entities)
256 {
257 if (entity.Coordinates == point) return entity;
258 }
259 return null;
260 }
261
262 /// <summary>
263 /// Get a player at a certain place on the map.
264 /// </summary>
265 /// <param name="point">The coordinates.</param>
266 /// <returns>The player, or null if none is at that location.</returns>
267 public Player GetPlayerAtCoordinates(Point point)
268 {
269 foreach (Player player in State.mCharacters)
270 {
271 if (player != null && player.Coordinates == point) return player;
272 }
273 return null;
274 }
275
276 /// <summary>
277 /// Determine if a cell is open, depending on the static scenery
278 /// of the map and if there are any collidable entities.
279 /// </summary>
280 /// <param name="point">The coordinates.</param>
281 /// <returns>True if the cell is open; false otherwise.</returns>
282 public bool IsCellOpen(Point point)
283 {
284 if (!State.Map.IsCellOpen(point)) return false;
285 IEntity entity = GetEntityAtCoordinates(point);
286 if (entity != null && entity.IsCollidable) return false;
287 Player player = GetPlayerAtCoordinates(point);
288 if (player != null) return false;
289 return true;
290 }
291
292 /// <summary>
293 /// Remove a specific entity from the game. The entity can still
294 /// be tracked some other way, but it won't included when the game is
295 /// updating and drawing stuff.
296 /// </summary>
297 /// <param name="entity">The entity.</param>
298 /// <returns>The entity that was removed, or null if no entity was removed.</returns>
299 public IEntity RemoveEntity(IEntity entity)
300 {
301 if (State.Entities.Remove(entity)) return entity;
302 return null;
303 }
304
305 /// <summary>
306 /// Move on to the next map, and advance the level.
307 /// </summary>
308 public void AdvanceLevel()
309 {
310 // TODO: Load the next map, etc...
311 //TODO somehow get next map
312 State.Entities.Clear();
313 String nextMap = State.Map.Next;
314 State.Map = mContentManager.Load<Map>("Maps/"+nextMap);
315 for (int i = 0; i < State.mCharacters.Length; i++)
316 {
317 State.mCharacters[i].Coordinates = State.Map.GetStartingPositionForPlayer(i + 1);
318 }
319 State.Entities = State.Map.GetAllEntities(this);
320 }
321
322 /// <summary>
323 /// Restart the current level.
324 /// </summary>
325 public void Reset()
326 {
327 State.Map.Reset();
328 // TODO: Do other stuff to reset everything.
329 }
330
331
332 public Game()
333 {
334
335 }
336 public void LoadContent(ContentManager contentManager)
337 {
338 mContentManager = contentManager;
339 menu = mContentManager.Load<SpriteFont>("menuFont");
340
341 }
342
343 public void UnloadContent()
344 {
345 }
346
347 private int GetPlayerNumber(Object playerIdentifier)
348 {
349 for (int i = 0; i < mPlayerIdentifiers.Length; i++)
350 {
351 if (mPlayerIdentifiers[i] == playerIdentifier) return i;
352 }
353 throw new Exception("Illegal player identifier" + playerIdentifier);
354 }
355
356 public Vector2 PreferredScreenSize
357 {
358 get { return new Vector2(800, 600); }
359 }
360
361 public int MinimumSupportedPlayers
362 {
363 get { return 1; }
364 }
365
366 public int MaximumSupportedPlayers
367 {
368 get { return 4; }
369 }
370
371 public void ResetGame(object[] playerIdentifiers, object thisPlayer)
372 {
373 int numPlayers = playerIdentifiers.Count();
374
375 mPlayerIdentifiers = new object[numPlayers];
376 for (int i = 0; i < numPlayers; i++) mPlayerIdentifiers[i] = playerIdentifiers[i];
377
378 mThisPlayerID = GetPlayerNumber(thisPlayer);
379
380 State = new GameState(numPlayers);
381 mInputs = new NextInputs(numPlayers);
382 State.mDisplay = new Display(this);
383 State.mDisplay.LoadContent(mContentManager);
384
385 // Load the tilemap.
386 Texture2D mapTiles = mContentManager.Load<Texture2D>("graphics/wallAndFloorTilesNoEdgeScale");
387 Tilemap tilemap = new Tilemap(mapTiles, 10, 7);
388 tilemap.SetTile('`', new Point(0, 2), TileFlags.Closed | TileFlags.Wall);
389 tilemap.SetTile('~', new Point(1, 2), TileFlags.Closed | TileFlags.Wall);
390 tilemap.SetTile('!', new Point(2, 2), TileFlags.Closed | TileFlags.Wall);
391 tilemap.SetTile('@', new Point(3, 2), TileFlags.Closed | TileFlags.Wall);
392 tilemap.SetTile('#', new Point(4, 2), TileFlags.Closed | TileFlags.Wall);
393 tilemap.SetTile('$', new Point(5, 2), TileFlags.Closed | TileFlags.Wall);
394 tilemap.SetTile('%', new Point(6, 2), TileFlags.Closed | TileFlags.Wall);
395 tilemap.SetTile('^', new Point(8, 2), TileFlags.Closed | TileFlags.Wall);
396 tilemap.SetTile('&', new Point(9, 2), TileFlags.Closed | TileFlags.Wall);
397 tilemap.SetTile('*', new Point(0, 3), TileFlags.Closed | TileFlags.Wall);
398 tilemap.SetTile('(', new Point(1, 3), TileFlags.Closed | TileFlags.Wall);
399 tilemap.SetTile(')', new Point(2, 3), TileFlags.Closed | TileFlags.Wall);
400 tilemap.SetTile('-', new Point(3, 3), TileFlags.Closed | TileFlags.Wall);
401 tilemap.SetTile('=', new Point(4, 3), TileFlags.Closed | TileFlags.Wall);
402 tilemap.SetTile('_', new Point(5, 3), TileFlags.Closed | TileFlags.Wall);
403 tilemap.SetTile('+', new Point(6, 3), TileFlags.Closed | TileFlags.Wall);
404 tilemap.SetTile('|', new Point(8, 3), TileFlags.Closed | TileFlags.Wall);
405 tilemap.SetTile('[', new Point(0, 4), TileFlags.Default);
406 tilemap.SetTile(']', new Point(1, 4), TileFlags.Default);
407 tilemap.SetTile('{', new Point(2, 4), TileFlags.Default);
408 tilemap.SetTile('}', new Point(3, 4), TileFlags.Default);
409 tilemap.SetTile('?', new Point(4, 4), TileFlags.Default);
410 tilemap.SetTile(',', new Point(7, 4), TileFlags.Default);
411 tilemap.SetTile('.', new Point(8, 4), TileFlags.Default);
412 tilemap.SetTile('\\', new Point(9, 4), TileFlags.Default);
413 tilemap.SetTile(';', new Point(0, 5), TileFlags.Default);
414 tilemap.SetTile(':', new Point(1, 5), TileFlags.Default);
415 tilemap.SetTile('\'', new Point(2, 5), TileFlags.Default);
416 tilemap.SetTile('"', new Point(3, 5), TileFlags.Default);
417 tilemap.SetTile(' ', new Point(4, 5), TileFlags.Default);
418 tilemap.SetTile('<', new Point(7, 5), TileFlags.Default);
419 tilemap.SetTile('>', new Point(8, 5), TileFlags.Default);
420 tilemap.SetTile('/', new Point(9, 5), TileFlags.Default);
421 Map.Tilemap = tilemap;
422
423 // Load the first map.
424 State.Map = mContentManager.Load<Map>("Maps/colosseumClosed");
425 State.Entities = State.Map.GetAllEntities(this);
426
427 mAIData = new AI(this);
428
429 /*
430 mPlayers.Clear();
431 for (int i = 0; i < PlayerIdentifiers.Length; i++)
432 {
433 Human player = new Human(mMap, "");
434 mPlayers.Add(player);
435 mDisplay.AddCharacters(player);
436 mPlayers.Add(player);
437 mDisplay.AddCharacters(player);
438 }
439 this.playerIdentifiers = PlayerIdentifiers;
440 for (int i = 0; i < mPlayers.Count; i++)
441 {
442 Point starting = mMap.GetStartingPositionForPlayer(i + 1);
443 mPlayers[i].Spawn(new Vector2(starting.X, starting.Y));
444 }
445 */
446 }
447
448 public long CurrentFrameNumber
449 {
450 get { return State.FrameNumber; }
451 }
452
453 public long CurrentChecksum
454 {
455 get { return 0; }
456 }
457
458 public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed)
459 {
460 //code from Prof Jensen's TestHarness
461 int player = GetPlayerNumber(playerIdentifier);
462
463 if (isKeyPressed && !mInputs.KeysPressed[player].Contains(key))
464 mInputs.KeysPressed[player].Add(key);
465
466 if (!isKeyPressed && !mInputs.KeysReleased[player].Contains(key))
467 mInputs.KeysReleased[player].Add(key);
468
469 }
470
471 public void ApplyMouseLocationInput(object playerIdentifier, int x, int y)
472 {
473
474 }
475
476 public void ApplyMouseButtonInput(object playerIdentifier, bool isButtonPressed)
477 {
478
479 }
480
481 public bool IsGameOver(object playerIdentifier)
482 {
483 return false;
484 }
485
486 public bool IsTerminated(object playerIdentifier)
487 {
488 return false;
489 }
490
491 public long Update(TimeSpan elapsedTime)
492 {
493 State.AdvanceFrame(mInputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.
494 State.mDisplay.Update(elapsedTime, mThisPlayerID);
495 State.Entities.ForEach(delegate(IEntity e)
496 {
497 IMonster m = e as IMonster;
498 if (m != null)
499 {
500 if (State.mCharacters[0] != null && mAIData.spaceVisible(e.Coordinates, State.mCharacters[0].Coordinates))
501 {
502 m.Chasing(State.mCharacters[0].Coordinates);
503 }
504 else
505 {
506 m.DefaultAction();
507 }
508 }
509 e.Update(elapsedTime);
510 });
511 //State.Entities.ForEach(delegate(IEntity e) { e.Update(elapsedTime); });
512 mInputs = new NextInputs(State.NumberOfPlayers); // Start with inputs cleared on the next frame.
513 //mDisplay.Update(elapsedTime);
514 return State.FrameNumber;
515
516 }
517
518 public long Draw(SpriteBatch spriteBatch)
519 {
520 bool allCharactersSelected = true;
521 for (int i = 0; i < State.NumberOfPlayers; i++)
522 {
523 //If player has not selected a player yet let them select one.
524 if (State.mCharacters[i] == null)
525 {
526 allCharactersSelected = false;
527 if (State.GetKeysDown(i).Contains(Keys.M))
528 {
529 State.mCharacters[i] = new Melee(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
530 State.mCharacters[i].LoadContent(mContentManager);
531 }
532 else if (State.GetKeysDown(i).Contains(Keys.R))
533 {
534 State.mCharacters[i] = new Ranged(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
535 State.mCharacters[i].LoadContent(mContentManager);
536 }
537 }
538 }
539 if (allCharactersSelected)
540 {
541
542 State.mDisplay.Draw(spriteBatch);
543 }
544 else
545 {
546 spriteBatch.GraphicsDevice.Clear(Color.Black);
547 spriteBatch.DrawString(menu, "Press R to select a Ranged Character and M to select a Melee Character", new Vector2(30, 30), Color.RosyBrown);
548 }
549 return CurrentFrameNumber;
550 }
551
552 #endregion
553
554
555 #region Private Variables
556
557 SpriteFont menu;
558 AI mAIData;
559 ContentManager mContentManager;
560 NextInputs mInputs;
561
562 Object[] mPlayerIdentifiers;
563 int mThisPlayerID;
564
565 #endregion
566 }
567 }
This page took 0.059552 seconds and 4 git commands to generate.