]> Dogcows Code - chaz/carfire/blob - CarFire/CarFire/CarFire/Game.cs
AI initial calculations almost done, still a few small bugs. Used to determine 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 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 public AI AIData;
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 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));
367
368 State.Map = mContentManager.Load<Map>("Maps/level1");
369 State.Map.Tilemap = tilemap;
370 State.Entities = State.Map.GetAllEntities(this);
371
372 State.AIData = new AI(this);
373
374 /*
375 mPlayers.Clear();
376 for (int i = 0; i < PlayerIdentifiers.Length; i++)
377 {
378 Human player = new Human(mMap, "");
379 mPlayers.Add(player);
380 mDisplay.AddCharacters(player);
381 mPlayers.Add(player);
382 mDisplay.AddCharacters(player);
383 }
384 this.playerIdentifiers = PlayerIdentifiers;
385 for (int i = 0; i < mPlayers.Count; i++)
386 {
387 Point starting = mMap.GetStartingPositionForPlayer(i + 1);
388 mPlayers[i].Spawn(new Vector2(starting.X, starting.Y));
389 }
390 */
391 }
392
393 public long CurrentFrameNumber
394 {
395 get { return State.FrameNumber; }
396 }
397
398 public long CurrentChecksum
399 {
400 get { return 0; }
401 }
402
403 public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed)
404 {
405 //code from Prof Jensen's TestHarness
406 int player = GetPlayerNumber(playerIdentifier);
407
408 if (isKeyPressed && !mInputs.KeysPressed[player].Contains(key))
409 mInputs.KeysPressed[player].Add(key);
410
411 if (!isKeyPressed && !mInputs.KeysReleased[player].Contains(key))
412 mInputs.KeysReleased[player].Add(key);
413
414 }
415
416 public void ApplyMouseLocationInput(object playerIdentifier, int x, int y)
417 {
418
419 }
420
421 public void ApplyMouseButtonInput(object playerIdentifier, bool isButtonPressed)
422 {
423
424 }
425
426 public bool IsGameOver(object playerIdentifier)
427 {
428 return false;
429 }
430
431 public bool IsTerminated(object playerIdentifier)
432 {
433 return false;
434 }
435
436 public long Update(TimeSpan elapsedTime)
437 {
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;
444
445 }
446
447 public long Draw(SpriteBatch spriteBatch)
448 {
449 bool allCharactersSelected = true;
450 for (int i = 0; i < State.NumberOfPlayers; i++)
451 {
452 //If player has not selected a player yet let them select one.
453 if (State.mCharacters[i] == null)
454 {
455 allCharactersSelected = false;
456 if (State.GetKeysDown(i).Contains(Keys.M))
457 {
458 State.mCharacters[i] = new Melee(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
459 State.mCharacters[i].LoadContent(mContentManager);
460 }
461 else if (State.GetKeysDown(i).Contains(Keys.R))
462 {
463 State.mCharacters[i] = new Ranged(this, "", State.Map.GetStartingPositionForPlayer(i + 1), i);
464 State.mCharacters[i].LoadContent(mContentManager);
465 }
466 }
467 }
468 if (allCharactersSelected)
469 {
470
471 State.mDisplay.Draw(spriteBatch);
472 }
473 else
474 {
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);
477 }
478 return CurrentFrameNumber;
479 }
480
481 #endregion
482
483
484 #region Private Variables
485
486 SpriteFont menu;
487
488 ContentManager mContentManager;
489 NextInputs mInputs;
490
491 Object[] mPlayerIdentifiers;
492 int mThisPlayerID;
493
494 #endregion
495 }
496 }
This page took 0.052171 seconds and 5 git commands to generate.