\r
namespace CarFire\r
{\r
- class Game : IDeterministicGame\r
+ // Everything in objects built from this class represent the critical game state\r
+ public class GameState\r
+ {\r
+ public long frameNumber;\r
+\r
+ private long checksum;\r
+ public long Checksum { get { return checksum; } }\r
+\r
+ public bool[] isGameOver;\r
+ public bool[] isTerminated;\r
+\r
+ // Since this is not a game, I'll just keep track of the user inputs as the game state.\r
+\r
+ public int[] mouseLocationX;\r
+ public int[] mouseLocationY;\r
+ public bool[] mouseButton;\r
+ public List<Keys>[] keysDown;\r
+ public int[] keypressCount;\r
+\r
+ public long elapsedTime;\r
+\r
+ /* Constructor */\r
+ public GameState()\r
+ {\r
+ frameNumber = 0;\r
+ checksum = 0;\r
+\r
+ isGameOver = new bool[4];\r
+ isTerminated = new bool[4];\r
+\r
+ mouseLocationX = new int[4];\r
+ mouseLocationY = new int[4];\r
+ mouseButton = new bool[4];\r
+ keysDown = new List<Keys>[4];\r
+ for (int i = 0; i < 4; i++)\r
+ keysDown[i] = new List<Keys>();\r
+ keypressCount = new int[4];\r
+\r
+ elapsedTime = 0;\r
+\r
+ checksum = 0;\r
+ }\r
+\r
+ /* The game engine! */\r
+ public void advanceFrame(NextInputs inputs, long milliseconds)\r
+ {\r
+ // Advance frame number\r
+ frameNumber++;\r
+\r
+ // Advance game - for the test harness, just record statistics and input states.\r
+\r
+ elapsedTime += milliseconds;\r
+\r
+ for (int player = 0; player < 4; player++)\r
+ {\r
+\r
+ //if (isGameOver[player])\r
+ // continue;\r
+\r
+ if (inputs.mousePressedChanged[player])\r
+ mouseButton[player] = inputs.mousePressed[player];\r
+\r
+ if (inputs.mouseLocationChanged[player])\r
+ {\r
+ mouseLocationX[player] = inputs.mouseLocationX[player];\r
+ mouseLocationY[player] = inputs.mouseLocationY[player];\r
+ }\r
+\r
+ foreach (Keys k in inputs.keysPressed[player])\r
+ if (!keysDown[player].Contains(k))\r
+ {\r
+ keysDown[player].Add(k);\r
+ keypressCount[player]++;\r
+ }\r
+\r
+ foreach (Keys k in inputs.keysReleased[player])\r
+ keysDown[player].Remove(k);\r
+\r
+ // If the mouse was pressed for a certain player, activate game over or terminated states as appropriate\r
+\r
+ if (inputs.mousePressed[player])\r
+ for (int p = 0; p < 4; p++)\r
+ {\r
+ int x = 200 * p + 10;\r
+ int y = 220;\r
+\r
+ if (mouseLocationX[player] >= x && mouseLocationY[player] >= y &&\r
+ mouseLocationX[player] < x + 25 && mouseLocationY[player] < y + 25)\r
+ {\r
+ isGameOver[p] = true;\r
+ }\r
+ y += 25;\r
+ if (mouseLocationX[player] >= x && mouseLocationY[player] >= y &&\r
+ mouseLocationX[player] < x + 25 && mouseLocationY[player] < y + 25)\r
+ {\r
+ isGameOver[p] = true;\r
+ isTerminated[p] = true;\r
+ }\r
+ }\r
+ \r
+\r
+ }\r
+\r
+ // Advance the checksum.\r
+\r
+ computeChecksum();\r
+\r
+ }\r
+\r
+ /* Just hash the values */\r
+ private long computeChecksum()\r
+ {\r
+ checksum += frameNumber;\r
+ for (int i = 0; i < 4; i++)\r
+ {\r
+ checksum = checksum + keypressCount[i];\r
+ checksum = checksum * 3 + (isGameOver[i] ? 1 : 2);\r
+ checksum = checksum * 3 + (isTerminated[i] ? 1 : 2);\r
+ foreach (Keys k in keysDown[i])\r
+ checksum = checksum * 257 + (int)k;\r
+ checksum = checksum * 25789 + mouseLocationX[i] * 259 + mouseLocationY[i] + 375;\r
+ checksum = checksum * 3 + (mouseButton[i] ? 1 : 2);\r
+\r
+ }\r
+ checksum += elapsedTime;\r
+\r
+ return checksum;\r
+ }\r
+ }\r
+ //code from Prof Jensen's TestHarness\r
+ // This class encapsulates inputs from the players.\r
+ public class NextInputs\r
+ {\r
+ public List<Keys>[] keysPressed;\r
+ public List<Keys>[] keysReleased;\r
+ public int[] mouseLocationX;\r
+ public int[] mouseLocationY;\r
+ public bool[] mouseLocationChanged;\r
+ public bool[] mousePressed;\r
+ public bool[] mousePressedChanged;\r
+\r
+ public NextInputs()\r
+ {\r
+ keysPressed = new List<Keys>[4];\r
+ keysReleased = new List<Keys>[4];\r
+ mouseLocationX = new int[4];\r
+ mouseLocationY = new int[4];\r
+ mouseLocationChanged = new bool[4];\r
+ mousePressed = new bool[4];\r
+ mousePressedChanged = new bool[4];\r
+ for (int i = 0; i < 4; i++)\r
+ keysPressed[i] = new List<Keys>();\r
+ for (int i = 0; i < 4; i++)\r
+ keysReleased[i] = new List<Keys>();\r
+ }\r
+ \r
+ }\r
+\r
+ public class Game : IDeterministicGame\r
{\r
#region IDeterministicGame Members\r
+ List<IPlayer> mPlayers;\r
+ NextInputs inputs;\r
+ Object[] playerIdentifiers;\r
+ Display mDisplay;\r
+ Map mMap;\r
+\r
+ GameState state;\r
+ int thisPlayerID;\r
\r
+ public Game()\r
+ {\r
+ mDisplay = new Display();\r
+ mPlayers = new List<IPlayer>();\r
+ playerIdentifiers = new Object[4];\r
+ }\r
public void LoadContent(ContentManager contentManager)\r
{\r
+ //Texture2D everything = contentManager.Load<Texture2D>("default");\r
+ mDisplay.LoadContent(contentManager);\r
+ int currentCenterX = 5; //Creates a map like the one in Display\r
+ int currentCenterY = 5;\r
+ mMap = contentManager.Load<Map>("Maps/stable");\r
+ Map.DefaultTile = contentManager.Load<Texture2D>("default");\r
+ mMap.CenterCell = new Vector2(currentCenterX, currentCenterY);\r
+ \r
}\r
\r
public void UnloadContent()\r
{\r
}\r
\r
+ private int idPlayer(Object playerIdentifier)\r
+ {\r
+ for (int i = 0; i < playerIdentifiers.Length; i++)\r
+ if (playerIdentifiers[i] == playerIdentifier)\r
+ return i;\r
+ throw new Exception("Illegal player identifier" + playerIdentifier);\r
+ }\r
+\r
public Vector2 PreferredScreenSize\r
{\r
get { return new Vector2(800, 600); }\r
get { return 4; }\r
}\r
\r
- public void ResetGame(object[] playerIdentifiers, object thisPlayer)\r
+ public void ResetGame(object[] PlayerIdentifiers, object thisPlayer)\r
{\r
+ // Now the test harness will at least run with less than 4 players...\r
+ int numPlayers = PlayerIdentifiers.Count();\r
+ for (int i = 0; i < numPlayers; i++)\r
+ this.playerIdentifiers[i] = PlayerIdentifiers[i];\r
+\r
+ // Create new game state and inputs objects.\r
+\r
+ state = new GameState();\r
+ inputs = new NextInputs();\r
+\r
+ // Record 'this' player.\r
+\r
+ this.thisPlayerID = idPlayer(thisPlayer);\r
+ /*\r
+ mPlayers.Clear();\r
+ for (int i = 0; i < PlayerIdentifiers.Length; i++)\r
+ {\r
+ Human player = new Human(mMap, "");\r
+ mPlayers.Add(player);\r
+ mDisplay.AddCharacters(player);\r
+ mPlayers.Add(player);\r
+ mDisplay.AddCharacters(player);\r
+ }\r
+ this.playerIdentifiers = PlayerIdentifiers;\r
+ for (int i = 0; i < mPlayers.Count; i++) \r
+ {\r
+ Point starting = mMap.GetStartingPositionForPlayer(i + 1);\r
+ mPlayers[i].Spawn(new Vector2(starting.X, starting.Y));\r
+ }\r
+ */\r
+ \r
}\r
\r
public long CurrentFrameNumber\r
{\r
- get { return 0; }\r
+ get { return state.frameNumber; }\r
}\r
\r
public long CurrentChecksum\r
\r
public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed)\r
{\r
+ //code from Prof Jensen's TestHarness\r
+ int player = idPlayer(playerIdentifier);\r
+\r
+ if (isKeyPressed && !inputs.keysPressed[player].Contains(key))\r
+ inputs.keysPressed[player].Add(key);\r
+\r
+ if (!isKeyPressed && !inputs.keysReleased[player].Contains(key))\r
+ inputs.keysReleased[player].Add(key);\r
+ \r
}\r
\r
public void ApplyMouseLocationInput(object playerIdentifier, int x, int y)\r
{\r
+\r
}\r
\r
public void ApplyMouseButtonInput(object playerIdentifier, bool isButtonPressed)\r
{\r
+\r
}\r
\r
public bool IsGameOver(object playerIdentifier)\r
{\r
- return true;\r
+ return false;\r
}\r
\r
public bool IsTerminated(object playerIdentifier)\r
{\r
- return true;\r
+ return false;\r
}\r
\r
- public long Update(TimeSpan timespan)\r
+ public long Update(TimeSpan elapsedTime)\r
{\r
- return CurrentFrameNumber;\r
+ state.advanceFrame(inputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.\r
+ mDisplay.Update(elapsedTime, state);\r
+ inputs = new NextInputs(); // Start with inputs cleared on the next frame.\r
+ //mDisplay.Update(elapsedTime);\r
+ return state.frameNumber;\r
+ \r
}\r
\r
public long Draw(SpriteBatch spriteBatch)\r
{\r
+ mDisplay.Draw(spriteBatch);\r
return CurrentFrameNumber;\r
}\r
\r