]> Dogcows Code - chaz/carfire/blob - Project06/CS 3505 Project 06/CS 3505 Project 06/CS 3505/TestHarness.cs
883e8a09676d15b86615d228fa0a7c12042118af
[chaz/carfire] / Project06 / CS 3505 Project 06 / CS 3505 Project 06 / CS 3505 / TestHarness.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using Microsoft.Xna.Framework.Content;
6 using Microsoft.Xna.Framework.Input;
7 using Microsoft.Xna.Framework;
8 using Microsoft.Xna.Framework.Graphics;
9
10 namespace CS_3505_Project_06.CS_3505
11 {
12 // Everything in objects built from this class represent the critical game state
13 public class GameState
14 {
15 public long frameNumber;
16
17 private long checksum;
18 public long Checksum { get { return checksum; } }
19
20 public bool[] isGameOver;
21 public bool[] isTerminated;
22
23 // Since this is not a game, I'll just keep track of the user inputs as the game state.
24
25 public int[] mouseLocationX;
26 public int[] mouseLocationY;
27 public bool[] mouseButton;
28 public List<Keys>[] keysDown;
29 public int[] keypressCount;
30
31 public long elapsedTime;
32
33 /* Constructor */
34 public GameState()
35 {
36 frameNumber = 0;
37 checksum = 0;
38
39 isGameOver = new bool[4];
40 isTerminated = new bool[4];
41
42 mouseLocationX = new int[4];
43 mouseLocationY = new int[4];
44 mouseButton = new bool[4];
45 keysDown = new List<Keys>[4];
46 for (int i = 0; i < 4; i++)
47 keysDown[i] = new List<Keys>();
48 keypressCount = new int[4];
49
50 elapsedTime = 0;
51
52 checksum = 0;
53 }
54
55 /* The game engine! */
56 public void advanceFrame(NextInputs inputs, long milliseconds)
57 {
58 // Advance frame number
59 frameNumber++;
60
61 // Advance game - for the test harness, just record statistics and input states.
62
63 elapsedTime += milliseconds;
64
65 for (int player = 0; player < 4; player++)
66 {
67 if (isGameOver[player])
68 continue;
69
70 if (inputs.mousePressedChanged[player])
71 mouseButton[player] = inputs.mousePressed[player];
72
73 if (inputs.mouseLocationChanged[player])
74 {
75 mouseLocationX[player] = inputs.mouseLocationX[player];
76 mouseLocationY[player] = inputs.mouseLocationY[player];
77 }
78
79 foreach (Keys k in inputs.keysPressed[player])
80 if (!keysDown[player].Contains(k))
81 {
82 keysDown[player].Add(k);
83 keypressCount[player]++;
84 }
85
86 foreach (Keys k in inputs.keysReleased[player])
87 keysDown[player].Remove(k);
88
89 // If the mouse was pressed for a certain player, activate game over or terminated states as appropriate
90
91 if (inputs.mousePressed[player])
92 for (int p = 0; p < 4; p++)
93 {
94 int x = 200 * p + 10;
95 int y = 220;
96
97 if (mouseLocationX[player] >= x && mouseLocationY[player] >= y &&
98 mouseLocationX[player] < x + 25 && mouseLocationY[player] < y + 25)
99 {
100 isGameOver[p] = true;
101 }
102 y += 25;
103 if (mouseLocationX[player] >= x && mouseLocationY[player] >= y &&
104 mouseLocationX[player] < x + 25 && mouseLocationY[player] < y + 25)
105 {
106 isGameOver[p] = true;
107 isTerminated[p] = true;
108 }
109 }
110
111 }
112
113 // Advance the checksum.
114
115 computeChecksum();
116
117 }
118
119 /* Just hash the values */
120 private long computeChecksum()
121 {
122 checksum += frameNumber;
123 for (int i = 0; i < 4; i++)
124 {
125 checksum = checksum + keypressCount[i];
126 checksum = checksum * 3 + (isGameOver[i] ? 1 : 2);
127 checksum = checksum * 3 + (isTerminated[i] ? 1 : 2);
128 foreach (Keys k in keysDown[i])
129 checksum = checksum * 257 + (int) k;
130 checksum = checksum * 25789 + mouseLocationX[i] * 259 + mouseLocationY[i] + 375;
131 checksum = checksum * 3 + (mouseButton[i] ? 1 : 2);
132
133 }
134 checksum += elapsedTime;
135
136 return checksum;
137 }
138 }
139
140 // This class encapsulates inputs from the players.
141 public class NextInputs
142 {
143 public List<Keys>[] keysPressed;
144 public List<Keys>[] keysReleased;
145 public int[] mouseLocationX;
146 public int[] mouseLocationY;
147 public bool[] mouseLocationChanged;
148 public bool[] mousePressed;
149 public bool[] mousePressedChanged;
150
151 public NextInputs()
152 {
153 keysPressed = new List<Keys>[4];
154 keysReleased = new List<Keys>[4];
155 mouseLocationX = new int[4];
156 mouseLocationY = new int[4];
157 mouseLocationChanged = new bool[4];
158 mousePressed = new bool[4];
159 mousePressedChanged = new bool[4];
160 for (int i = 0; i < 4; i++)
161 keysPressed[i] = new List<Keys>();
162 for (int i = 0; i < 4; i++)
163 keysReleased[i] = new List<Keys>();
164 }
165 }
166
167 public class TestHarness : IDeterministicGame
168 {
169 GameState state;
170 NextInputs inputs;
171 Object[] playerIdentifiers;
172 int thisPlayerID;
173
174 // Instance variables here contribute to the display, but not the game state
175
176 Texture2D crosshair;
177 SpriteFont font;
178
179 // Constructor
180
181 public TestHarness()
182 {
183 playerIdentifiers = new Object[4];
184 }
185
186 // Helper methods
187
188 private int idPlayer(Object playerIdentifier)
189 {
190 for (int i = 0; i < playerIdentifiers.Length; i++)
191 if (playerIdentifiers[i] == playerIdentifier)
192 return i;
193 throw new Exception("Illegal player identifier" + playerIdentifier);
194 }
195
196 // Implementation of the DeterministicGame interface
197 #region IDeterministicGame Members
198
199 public void LoadContent(ContentManager contentManager)
200 {
201 crosshair = contentManager.Load<Texture2D>("CS 3505/Crosshair");
202 font = contentManager.Load<SpriteFont>("CS 3505/GameFont");
203 }
204
205 public void UnloadContent()
206 {
207 // Nothing to do - the content manager will take care of it.
208 }
209
210 public Vector2 PreferredScreenSize
211 {
212 get { return new Vector2(800, 600); }
213 }
214
215 public int MinimumSupportedPlayers
216 {
217 get { return 4; }
218 }
219
220 public int MaximumSupportedPlayers
221 {
222 get { return 4; }
223 }
224
225 public void ResetGame(Object[] playerIdentifiers, Object thisPlayer)
226 {
227 //if (playerIdentifiers.Length != 4)
228 // throw new Exception("This game requires four players.");
229
230 // Copy the player identifiers - do not rely on the array parameter not changing.
231
232 // Now the test harness will at least run with less than 4 players...
233 int numPlayers = playerIdentifiers.Count();
234 for (int i = 0; i < numPlayers; i++)
235 this.playerIdentifiers[i] = playerIdentifiers[i];
236
237 // Create new game state and inputs objects.
238
239 state = new GameState();
240 inputs = new NextInputs();
241
242 // Record 'this' player.
243
244 this.thisPlayerID = idPlayer(thisPlayer);
245 }
246
247 public long CurrentFrameNumber
248 {
249 get { return state.frameNumber; }
250 }
251
252 public long CurrentChecksum
253 {
254 get { return state.Checksum; }
255 }
256
257 public void ApplyKeyInput(Object playerIdentifier, Keys key, bool isKeyPressed)
258 {
259 int player = idPlayer(playerIdentifier);
260
261 if (isKeyPressed && !inputs.keysPressed[player].Contains(key))
262 inputs.keysPressed[player].Add(key);
263
264 if (!isKeyPressed && !inputs.keysReleased[player].Contains(key))
265 inputs.keysReleased[player].Add(key);
266 }
267
268 public void ApplyMouseLocationInput(Object playerIdentifier, int x, int y)
269 {
270 int player = idPlayer(playerIdentifier);
271 inputs.mouseLocationX[player] = x;
272 inputs.mouseLocationY[player] = y;
273 inputs.mouseLocationChanged[player] = true;
274 }
275
276 public void ApplyMouseButtonInput(Object playerIdentifier, bool isButtonPressed)
277 {
278 int player = idPlayer(playerIdentifier);
279 inputs.mousePressed[player] = isButtonPressed;
280 inputs.mousePressedChanged[player] = true;
281 }
282
283 public bool IsGameOver(Object playerIdentifier)
284 {
285 int player = idPlayer(playerIdentifier);
286 return state.isGameOver[player] ;
287 }
288
289 public bool IsTerminated(object playerIdentifier)
290 {
291 int player = idPlayer(playerIdentifier);
292 return state.isTerminated[player];
293 }
294
295 public long Update(TimeSpan elapsedTime)
296 {
297 state.advanceFrame(inputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.
298
299 inputs = new NextInputs(); // Start with inputs cleared on the next frame.
300
301 return state.frameNumber;
302 }
303
304 public long Draw(SpriteBatch spriteBatch)
305 {
306 centerString(spriteBatch, Color.White, "CS 3505 - Software Practice 2", 0, 800, 0);
307 centerString(spriteBatch, Color.White, "Test Harness", 0, 800, 25);
308 centerString(spriteBatch, Color.White, "Debug output", 0, 800, 50);
309
310 nameIntPair(spriteBatch, Color.White, "Frame:", state.frameNumber, 10, 150, 100);
311 nameHexPair(spriteBatch, Color.White, "Checksum:", state.Checksum, 215, 515, 100);
312 nameDecPair(spriteBatch, Color.White, "Elapsed Time:", state.elapsedTime / 1000.0f, 570, 790, 100);
313
314 printPlayer(spriteBatch, Color.Turquoise, 0, 10, 190, 170);
315 printPlayer(spriteBatch, Color.Wheat, 1, 210, 390, 170);
316 printPlayer(spriteBatch, Color.Tomato, 2, 410, 590, 170);
317 printPlayer(spriteBatch, Color.Violet, 3, 610, 790, 170);
318
319 if (!state.isGameOver[0])
320 spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[0] - 5, state.mouseLocationY[0] - 5), Color.Turquoise);
321 if (!state.isGameOver[1])
322 spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[1] - 5, state.mouseLocationY[1] - 5), Color.Wheat);
323 if (!state.isGameOver[2])
324 spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[2] - 5, state.mouseLocationY[2] - 5), Color.Tomato);
325 if (!state.isGameOver[3])
326 spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[3] - 5, state.mouseLocationY[3] - 5), Color.Violet);
327
328 spriteBatch.Draw(crosshair, new Vector2(Mouse.GetState().X - 5, Mouse.GetState().Y - 5), Color.White);
329
330 return state.frameNumber;
331 }
332
333 #endregion
334
335 void printPlayer(SpriteBatch spriteBatch, Color c, int player, float left, float right, float top)
336 {
337 leftJustify(spriteBatch, c, String.Format("Player {0}", player+1), left, top);
338 top += 10;
339 leftJustify(spriteBatch, c, "_________", left, top);
340 top += 40;
341 nameIntPair(spriteBatch, c, "[X] Game Over", state.isGameOver[player]?1:0, left, right, top);
342 top += 25;
343 nameIntPair(spriteBatch, c, "[X] Terminated", state.isTerminated[player] ? 1 : 0, left, right, top);
344 top += 40;
345 nameIntPair(spriteBatch, c, "Mouse X", (int)state.mouseLocationX[player], left, right, top);
346 top += 25;
347 nameIntPair(spriteBatch, c, "Mouse Y", (int)state.mouseLocationY[player], left, right, top);
348 top += 40;
349 leftJustify(spriteBatch, c, "Mouse", left, top);
350 rightJustify(spriteBatch, c, state.mouseButton[player]?"Pressed":"Released", right, top);
351 top += 40;
352 nameIntPair(spriteBatch, c, "Key count", (int)state.keypressCount[player], left, right, top);
353 top += 25;
354 leftJustify(spriteBatch, c, "Keys", left, top);
355 if (state.keysDown[player].Count == 0)
356 rightJustify(spriteBatch, c, "None", right, top);
357 else
358 foreach (Keys k in state.keysDown[player])
359 {
360 rightJustify(spriteBatch, c, k.ToString(), right, top);
361 top += 25;
362 }
363
364 }
365
366 void centerString(SpriteBatch spriteBatch, Color c, String s, float left, float right, float top)
367 {
368 Vector2 v = font.MeasureString(s);
369 float x = left + (right-left - v.X) / 2;
370 float y = top;
371 spriteBatch.DrawString(font, s, new Vector2(x, y), c);
372 }
373
374 void centerString(SpriteBatch spriteBatch, Color c, String s, Rectangle r)
375 {
376 Vector2 v = font.MeasureString(s);
377 float x = r.Left + (r.Width - v.X) / 2;
378 float y = r.Top + (r.Height - v.Y) / 2;
379 spriteBatch.DrawString(font, s, new Vector2(x, y), c);
380 }
381
382 void leftJustify(SpriteBatch spriteBatch, Color c, String s, float left, float top)
383 {
384 float x = left;
385 float y = top;
386 spriteBatch.DrawString(font, s, new Vector2(x, y), c);
387 }
388
389 void rightJustify(SpriteBatch spriteBatch, Color c, String s, float right, float top)
390 {
391 Vector2 v = font.MeasureString(s);
392 float x = right - v.X;
393 float y = top;
394 spriteBatch.DrawString(font, s, new Vector2(x, y), c);
395 }
396
397 void nameDecPair(SpriteBatch spriteBatch, Color c, String name, float number, float left, float right, float top)
398 {
399 String num = String.Format("{0:.00}", number);
400 leftJustify(spriteBatch, c, name, left, top);
401 rightJustify(spriteBatch, c, num, right, top);
402 }
403
404 void nameIntPair(SpriteBatch spriteBatch, Color c, String name, long number, float left, float right, float top)
405 {
406 String num = String.Format("{0}", number);
407 leftJustify(spriteBatch, c, name, left, top);
408 rightJustify(spriteBatch, c, num, right, top);
409 }
410
411 void nameHexPair(SpriteBatch spriteBatch, Color c, String name, long number, float left, float right, float top)
412 {
413 String num = String.Format("{0:x}", number);
414 leftJustify(spriteBatch, c, name, left, top);
415 rightJustify(spriteBatch, c, num, right, top);
416 }
417 }
418 }
This page took 0.048988 seconds and 3 git commands to generate.