]> Dogcows Code - chaz/carfire/blob - Project06/CS 3505 Project 06/CS 3505 Project 06/CS 3505/TestHarness.cs
initial upload
[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 for (int i = 0; i < 4; i++)
233 this.playerIdentifiers[i] = playerIdentifiers[i];
234
235 // Create new game state and inputs objects.
236
237 state = new GameState();
238 inputs = new NextInputs();
239
240 // Record 'this' player.
241
242 this.thisPlayerID = idPlayer(thisPlayer);
243 }
244
245 public long CurrentFrameNumber
246 {
247 get { return state.frameNumber; }
248 }
249
250 public long CurrentChecksum
251 {
252 get { return state.Checksum; }
253 }
254
255 public void ApplyKeyInput(Object playerIdentifier, Keys key, bool isKeyPressed)
256 {
257 int player = idPlayer(playerIdentifier);
258
259 if (isKeyPressed && !inputs.keysPressed[player].Contains(key))
260 inputs.keysPressed[player].Add(key);
261
262 if (!isKeyPressed && !inputs.keysReleased[player].Contains(key))
263 inputs.keysReleased[player].Add(key);
264 }
265
266 public void ApplyMouseLocationInput(Object playerIdentifier, int x, int y)
267 {
268 int player = idPlayer(playerIdentifier);
269 inputs.mouseLocationX[player] = x;
270 inputs.mouseLocationY[player] = y;
271 inputs.mouseLocationChanged[player] = true;
272 }
273
274 public void ApplyMouseButtonInput(Object playerIdentifier, bool isButtonPressed)
275 {
276 int player = idPlayer(playerIdentifier);
277 inputs.mousePressed[player] = isButtonPressed;
278 inputs.mousePressedChanged[player] = true;
279 }
280
281 public bool IsGameOver(Object playerIdentifier)
282 {
283 int player = idPlayer(playerIdentifier);
284 return state.isGameOver[player] ;
285 }
286
287 public bool IsTerminated(object playerIdentifier)
288 {
289 int player = idPlayer(playerIdentifier);
290 return state.isTerminated[player];
291 }
292
293 public long Update(TimeSpan elapsedTime)
294 {
295 state.advanceFrame(inputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.
296
297 inputs = new NextInputs(); // Start with inputs cleared on the next frame.
298
299 return state.frameNumber;
300 }
301
302 public long Draw(SpriteBatch spriteBatch)
303 {
304 centerString(spriteBatch, Color.White, "CS 3505 - Software Practice 2", 0, 800, 0);
305 centerString(spriteBatch, Color.White, "Test Harness", 0, 800, 25);
306 centerString(spriteBatch, Color.White, "Debug output", 0, 800, 50);
307
308 nameIntPair(spriteBatch, Color.White, "Frame:", state.frameNumber, 10, 150, 100);
309 nameHexPair(spriteBatch, Color.White, "Checksum:", state.Checksum, 215, 515, 100);
310 nameDecPair(spriteBatch, Color.White, "Elapsed Time:", state.elapsedTime / 1000.0f, 570, 790, 100);
311
312 printPlayer(spriteBatch, Color.Turquoise, 0, 10, 190, 170);
313 printPlayer(spriteBatch, Color.Wheat, 1, 210, 390, 170);
314 printPlayer(spriteBatch, Color.Tomato, 2, 410, 590, 170);
315 printPlayer(spriteBatch, Color.Violet, 3, 610, 790, 170);
316
317 if (!state.isGameOver[0])
318 spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[0] - 5, state.mouseLocationY[0] - 5), Color.Turquoise);
319 if (!state.isGameOver[1])
320 spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[1] - 5, state.mouseLocationY[1] - 5), Color.Wheat);
321 if (!state.isGameOver[2])
322 spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[2] - 5, state.mouseLocationY[2] - 5), Color.Tomato);
323 if (!state.isGameOver[3])
324 spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[3] - 5, state.mouseLocationY[3] - 5), Color.Violet);
325
326 spriteBatch.Draw(crosshair, new Vector2(Mouse.GetState().X - 5, Mouse.GetState().Y - 5), Color.White);
327
328 return state.frameNumber;
329 }
330
331 #endregion
332
333 void printPlayer(SpriteBatch spriteBatch, Color c, int player, float left, float right, float top)
334 {
335 leftJustify(spriteBatch, c, String.Format("Player {0}", player+1), left, top);
336 top += 10;
337 leftJustify(spriteBatch, c, "_________", left, top);
338 top += 40;
339 nameIntPair(spriteBatch, c, "[X] Game Over", state.isGameOver[player]?1:0, left, right, top);
340 top += 25;
341 nameIntPair(spriteBatch, c, "[X] Terminated", state.isTerminated[player] ? 1 : 0, left, right, top);
342 top += 40;
343 nameIntPair(spriteBatch, c, "Mouse X", (int)state.mouseLocationX[player], left, right, top);
344 top += 25;
345 nameIntPair(spriteBatch, c, "Mouse Y", (int)state.mouseLocationY[player], left, right, top);
346 top += 40;
347 leftJustify(spriteBatch, c, "Mouse", left, top);
348 rightJustify(spriteBatch, c, state.mouseButton[player]?"Pressed":"Released", right, top);
349 top += 40;
350 nameIntPair(spriteBatch, c, "Key count", (int)state.keypressCount[player], left, right, top);
351 top += 25;
352 leftJustify(spriteBatch, c, "Keys", left, top);
353 if (state.keysDown[player].Count == 0)
354 rightJustify(spriteBatch, c, "None", right, top);
355 else
356 foreach (Keys k in state.keysDown[player])
357 {
358 rightJustify(spriteBatch, c, k.ToString(), right, top);
359 top += 25;
360 }
361
362 }
363
364 void centerString(SpriteBatch spriteBatch, Color c, String s, float left, float right, float top)
365 {
366 Vector2 v = font.MeasureString(s);
367 float x = left + (right-left - v.X) / 2;
368 float y = top;
369 spriteBatch.DrawString(font, s, new Vector2(x, y), c);
370 }
371
372 void centerString(SpriteBatch spriteBatch, Color c, String s, Rectangle r)
373 {
374 Vector2 v = font.MeasureString(s);
375 float x = r.Left + (r.Width - v.X) / 2;
376 float y = r.Top + (r.Height - v.Y) / 2;
377 spriteBatch.DrawString(font, s, new Vector2(x, y), c);
378 }
379
380 void leftJustify(SpriteBatch spriteBatch, Color c, String s, float left, float top)
381 {
382 float x = left;
383 float y = top;
384 spriteBatch.DrawString(font, s, new Vector2(x, y), c);
385 }
386
387 void rightJustify(SpriteBatch spriteBatch, Color c, String s, float right, float top)
388 {
389 Vector2 v = font.MeasureString(s);
390 float x = right - v.X;
391 float y = top;
392 spriteBatch.DrawString(font, s, new Vector2(x, y), c);
393 }
394
395 void nameDecPair(SpriteBatch spriteBatch, Color c, String name, float number, float left, float right, float top)
396 {
397 String num = String.Format("{0:.00}", number);
398 leftJustify(spriteBatch, c, name, left, top);
399 rightJustify(spriteBatch, c, num, right, top);
400 }
401
402 void nameIntPair(SpriteBatch spriteBatch, Color c, String name, long number, float left, float right, float top)
403 {
404 String num = String.Format("{0}", number);
405 leftJustify(spriteBatch, c, name, left, top);
406 rightJustify(spriteBatch, c, num, right, top);
407 }
408
409 void nameHexPair(SpriteBatch spriteBatch, Color c, String name, long number, float left, float right, float top)
410 {
411 String num = String.Format("{0:x}", number);
412 leftJustify(spriteBatch, c, name, left, top);
413 rightJustify(spriteBatch, c, num, right, top);
414 }
415 }
416 }
This page took 0.049834 seconds and 4 git commands to generate.