X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fcarfire;a=blobdiff_plain;f=CarFire%2FCarFire%2FCarFire%2FGame.cs;h=38ec627d1456dcff5531f055f9e4a3f45808872d;hp=73745222e842d94bcf5b949404da2bb621866bdf;hb=16658241429e8befc3cb171a62163f36dedb6a33;hpb=32de3ceb04ed8123614002551d7cecd6dd5f41d0 diff --git a/CarFire/CarFire/CarFire/Game.cs b/CarFire/CarFire/CarFire/Game.cs index 7374522..38ec627 100644 --- a/CarFire/CarFire/CarFire/Game.cs +++ b/CarFire/CarFire/CarFire/Game.cs @@ -9,73 +9,258 @@ using Microsoft.Xna.Framework.Input; namespace CarFire { - //code from Prof Jensen's TestHarness - // This class encapsulates inputs from the players. + /// + /// Container class for the whole state of the game. + /// + public class GameState + { + #region Public Properties + + public long FrameNumber { get { return mFrameNumber; } } + + public long Checksum { get { return mChecksum; } } + + public int NumberOfPlayers { get { return mNumberOfPlayers; } } + + public Map Map; + public List Entities = new List(); + + #endregion + + + #region Public Methods + + /// + /// Construct a game state container with the number of players. + /// + /// Number of players. + public GameState(int numPlayers) + { + mNumberOfPlayers = numPlayers; + mFrameNumber = 0; + + mIsGameOver = new bool[numPlayers]; + mIsTerminated = new bool[numPlayers]; + + mMouseLocation = new Point[numPlayers]; + mMouseButton = new bool[numPlayers]; + mKeysDown = new List[numPlayers]; + for (int i = 0; i < numPlayers; i++) mKeysDown[i] = new List(); + + mKeypressCount = new int[numPlayers]; + mElapsedTime = 0; + mChecksum = 0; + } + + + /// + /// Should be called by the Game class to advance the state + /// to the next frame. + /// + /// The inputs that occurred to be + /// applied this coming frame. + /// Milliseconds; used for the checksum. + public void AdvanceFrame(NextInputs inputs, long milliseconds) + { + mFrameNumber++; + mElapsedTime += milliseconds; + + for (int player = 0; player < NumberOfPlayers; player++) + { + if (inputs.IsMousePressedChanged[player]) + { + mMouseButton[player] = inputs.MousePressed[player]; + } + + if (inputs.IsMouseLocationChanged[player]) + { + mMouseLocation[player] = inputs.MouseLocation[player]; + } + + foreach (Keys k in inputs.KeysPressed[player]) + { + if (!mKeysDown[player].Contains(k)) + { + mKeysDown[player].Add(k); + mKeypressCount[player]++; + } + } + + foreach (Keys k in inputs.KeysReleased[player]) mKeysDown[player].Remove(k); + } + + ComputeChecksum(); + } + + + /// + /// Get the mouse location for a player. + /// + /// Player Number. + /// Mouse location. + public Point GetMouseLocation(int playerNum) + { + return mMouseLocation[playerNum]; + } + + /// + /// Get the mouse button state for a player. + /// + /// Player number. + /// Mouse button state.. + public bool GetMouseButton(int playerNum) + { + return mMouseButton[playerNum]; + } + + /// + /// Get the keyboard state for a player. + /// + /// Player number. + /// Keyboard state. + public List GetKeysDown(int playerNum) + { + return mKeysDown[playerNum]; + } + + #endregion + + + #region Private Methods + + // Calculates a checksum for debugging network synchronization issues. + long ComputeChecksum() + { + mChecksum += FrameNumber; + for (int i = 0; i < NumberOfPlayers; i++) + { + mChecksum = mChecksum + mKeypressCount[i]; + mChecksum = mChecksum * 3 + (mIsGameOver[i] ? 1 : 2); + mChecksum = mChecksum * 3 + (mIsTerminated[i] ? 1 : 2); + foreach (Keys k in mKeysDown[i]) + mChecksum = mChecksum * 257 + (int)k; + mChecksum = mChecksum * 25789 + mMouseLocation[i].X * 259 + mMouseLocation[i].Y + 375; + mChecksum = mChecksum * 3 + (mMouseButton[i] ? 1 : 2); + + } + mChecksum += mElapsedTime; + + return mChecksum; + } + + #endregion + + + #region Private Variables + + int mNumberOfPlayers; + public Point[] mMouseLocation; + public bool[] mMouseButton; + public List[] mKeysDown; + + long mFrameNumber; + + bool[] mIsGameOver; + bool[] mIsTerminated; + + int[] mKeypressCount; + long mElapsedTime; + long mChecksum; + + #endregion + } + + /// + /// Container class for all the inputs for a single frame. + /// public class NextInputs { - public List[] keysPressed; - public List[] keysReleased; - public int[] mouseLocationX; - public int[] mouseLocationY; - public bool[] mouseLocationChanged; - public bool[] mousePressed; - public bool[] mousePressedChanged; - - public NextInputs() - { - keysPressed = new List[4]; - keysReleased = new List[4]; - mouseLocationX = new int[4]; - mouseLocationY = new int[4]; - mouseLocationChanged = new bool[4]; - mousePressed = new bool[4]; - mousePressedChanged = new bool[4]; - for (int i = 0; i < 4; i++) - keysPressed[i] = new List(); - for (int i = 0; i < 4; i++) - keysReleased[i] = new List(); + public List[] KeysPressed; + public List[] KeysReleased; + public Point[] MouseLocation; + public bool[] IsMouseLocationChanged; + public bool[] MousePressed; + public bool[] IsMousePressedChanged; + + public NextInputs(int numPlayers) + { + KeysPressed = new List[numPlayers]; + KeysReleased = new List[numPlayers]; + IsMouseLocationChanged = new bool[numPlayers]; + MousePressed = new bool[numPlayers]; + IsMousePressedChanged = new bool[numPlayers]; + for (int i = 0; i < numPlayers; i++) KeysPressed[i] = new List(); + for (int i = 0; i < numPlayers; i++) KeysReleased[i] = new List(); } } + + /// + /// The big kahuna. + /// public class Game : IDeterministicGame { - #region IDeterministicGame Members - List mPlayers; - NextInputs inputs; - Object[] playerIdentifiers; - Display mDisplay; - Map mMap; + #region Public Properties + + /// + /// Get the content manager associated with this game. + /// + public ContentManager ContentManager { get { return mContentManager; } } + + /// + /// Get the state. + /// + public GameState State; + + public bool[,] Grid + { + get + { + bool[,] grid = State.Map.Grid; + foreach (IEntity entity in State.Entities) + { + Point coordinates = entity.Coordinates; + grid[coordinates.X, coordinates.Y] = true; + } + return grid; + } + } + + #endregion + + + #region Public Methods + + public bool IsCellOpen(Point point) + { + if (!State.Map.IsCellOpen(point)) return false; + foreach (IEntity entity in State.Entities) + { + if (entity.Coordinates == point) return false; + } + return true; + } public Game() { - mDisplay = new Display(); - mPlayers = new List(); + mDisplay = new Display(this); } public void LoadContent(ContentManager contentManager) { - //Texture2D everything = contentManager.Load("default"); + mContentManager = contentManager; mDisplay.LoadContent(contentManager); - int currentCenterX = 5; //Creates a map like the one in Display - int currentCenterY = 5; - mMap = contentManager.Load("Maps/stable"); - Map.DefaultTile = contentManager.Load("default"); - mMap.CenterCell = new Vector2(currentCenterX, currentCenterY); - - Human player = new Human(mMap, ""); - player.LoadContent(contentManager); - mPlayers.Add(player); - mDisplay.AddCharacters(player); } public void UnloadContent() { } - private int idPlayer(Object playerIdentifier) + private int GetPlayerNumber(Object playerIdentifier) { - for (int i = 0; i < playerIdentifiers.Length; i++) - if (playerIdentifiers[i] == playerIdentifier) - return i; + for (int i = 0; i < mPlayerIdentifiers.Length; i++) + { + if (mPlayerIdentifiers[i] == playerIdentifier) return i; + } throw new Exception("Illegal player identifier" + playerIdentifier); } @@ -96,15 +281,43 @@ namespace CarFire public void ResetGame(object[] playerIdentifiers, object thisPlayer) { - foreach (IPlayer player in mPlayers) + int numPlayers = playerIdentifiers.Count(); + + mPlayerIdentifiers = new object[numPlayers]; + for (int i = 0; i < numPlayers; i++) mPlayerIdentifiers[i] = playerIdentifiers[i]; + + mThisPlayerID = GetPlayerNumber(thisPlayer); + + State = new GameState(numPlayers); + mInputs = new NextInputs(numPlayers); + + State.Map = mContentManager.Load("Maps/stable"); + State.Map.Game = this; + State.Entities = State.Map.GetAllEntities(); + Map.DefaultTile = mContentManager.Load("default"); + + /* + mPlayers.Clear(); + for (int i = 0; i < PlayerIdentifiers.Length; i++) { - player.Spawn(mMap.CenterCell); + Human player = new Human(mMap, ""); + mPlayers.Add(player); + mDisplay.AddCharacters(player); + mPlayers.Add(player); + mDisplay.AddCharacters(player); } + this.playerIdentifiers = PlayerIdentifiers; + for (int i = 0; i < mPlayers.Count; i++) + { + Point starting = mMap.GetStartingPositionForPlayer(i + 1); + mPlayers[i].Spawn(new Vector2(starting.X, starting.Y)); + } + */ } public long CurrentFrameNumber { - get { return 0; } + get { return State.FrameNumber; } } public long CurrentChecksum @@ -115,13 +328,14 @@ namespace CarFire public void ApplyKeyInput(object playerIdentifier, Keys key, bool isKeyPressed) { //code from Prof Jensen's TestHarness - int player = idPlayer(playerIdentifier); + int player = GetPlayerNumber(playerIdentifier); - if (isKeyPressed && !inputs.keysPressed[player].Contains(key)) - inputs.keysPressed[player].Add(key); + if (isKeyPressed && !mInputs.KeysPressed[player].Contains(key)) + mInputs.KeysPressed[player].Add(key); - if (!isKeyPressed && !inputs.keysReleased[player].Contains(key)) - inputs.keysReleased[player].Add(key); + if (!isKeyPressed && !mInputs.KeysReleased[player].Contains(key)) + mInputs.KeysReleased[player].Add(key); + } public void ApplyMouseLocationInput(object playerIdentifier, int x, int y) @@ -144,10 +358,15 @@ namespace CarFire return false; } - public long Update(TimeSpan timespan) + public long Update(TimeSpan elapsedTime) { - mDisplay.Update(timespan); - return CurrentFrameNumber; + State.AdvanceFrame(mInputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state. + mDisplay.Update(elapsedTime, State, mThisPlayerID); + State.Entities.ForEach(delegate(IEntity e) { e.Update(elapsedTime); }); + mInputs = new NextInputs(State.NumberOfPlayers); // Start with inputs cleared on the next frame. + //mDisplay.Update(elapsedTime); + return State.FrameNumber; + } public long Draw(SpriteBatch spriteBatch) @@ -157,5 +376,18 @@ namespace CarFire } #endregion + + + #region Private Variables + + Display mDisplay; + + ContentManager mContentManager; + NextInputs mInputs; + + Object[] mPlayerIdentifiers; + int mThisPlayerID; + + #endregion } }