using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework.Net; using System.Diagnostics; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; namespace CS_3505_Project_06 { public class NetworkGame { NetworkSession mNetworkSession; ILobby mLobby; IDeterministicGame mGame; TimeSpan mTargetTimeSpan = new TimeSpan(166666); public TimeSpan TargetTimeSpan { get { return mTargetTimeSpan; } } List lastPressedKeys; bool lastButtonPressed; Object[] playerIdentifiers = { "One", "Two", "Three", "Four" }; // Any objects will do, strings are easy to debug. // For debugging Object activePlayer; bool paused; long lastAutoPause; public SpriteFont font; public NetworkGame(ILobby lobby, IDeterministicGame game) { Debug.Assert(lobby != null && game != null); mLobby = lobby; mGame = game; // Begin: Test harness stuff lastPressedKeys = new List(); activePlayer = playerIdentifiers[0]; paused = false; // Reset the game - indicate that player #1 (player 0) owns this instance of the game. mGame.ResetGame(playerIdentifiers, playerIdentifiers[0]); } public LocalNetworkGamer LocalGamer { get { return mNetworkSession.LocalGamers[0]; } } // I added this as I needed a way to display all gamers not just the first gamer // -Brady public GamerCollection NetworkGamers { get { return mNetworkSession.AllGamers; } } public NetworkSession CreateSession() { return CreateSession(mGame.MaximumSupportedPlayers); } public NetworkSession CreateSession(int maxGamers) { Debug.Assert(mNetworkSession == null); mNetworkSession = NetworkSession.Create(NetworkSessionType.SystemLink, 1, maxGamers); mNetworkSession.AllowHostMigration = true; mNetworkSession.AllowJoinInProgress = false; return mNetworkSession; } // added so I can test if sessionExists and thus be able to call things on NetworkGame safely // -Brady public bool sessionExists() { return mNetworkSession != null; } public AvailableNetworkSessionCollection FindSessions() { return NetworkSession.Find(NetworkSessionType.SystemLink, 1, new NetworkSessionProperties()); } public NetworkSession JoinSession(AvailableNetworkSession availableSession) { Debug.Assert(mNetworkSession == null); mNetworkSession = NetworkSession.Join(availableSession); return mNetworkSession; } public void LeaveSession() { Debug.Assert(mNetworkSession != null); mNetworkSession.Dispose(); mNetworkSession = null; } public void SimulateBadNetwork() { Debug.Assert(mNetworkSession != null); mNetworkSession.SimulatedLatency = new TimeSpan(0, 0, 0, 0, 200); mNetworkSession.SimulatedPacketLoss = 0.1f; } public void Update(GameTime gameTime) { if (mNetworkSession == null) { mLobby.Update(gameTime, this); } else { mNetworkSession.Update(); if (mNetworkSession.SessionState == NetworkSessionState.Lobby) { if (mNetworkSession.IsHost && mNetworkSession.AllGamers.Count >= mGame.MinimumSupportedPlayers && mNetworkSession.IsEveryoneReady) { mNetworkSession.StartGame(); mNetworkSession.ResetReady(); } else { mLobby.Update(gameTime, this); } } else if (mNetworkSession.SessionState == NetworkSessionState.Playing) { // TODO: in-game update stuff UpdateTestHarness(gameTime); mGame.Update(mTargetTimeSpan); } } } public void Draw(GameTime gameTime, SpriteBatch spriteBatch) { mLobby.Draw(spriteBatch); DrawTestHarness(gameTime, spriteBatch); } void UpdateTestHarness(GameTime gameTime) { // Get user's input state. KeyboardState keyState = Keyboard.GetState(); MouseState mouseState = Mouse.GetState(); // Make a list of the keys pressed or released this frame. List pressedKeys = new List(); List releasedKeys = new List(); Keys[] pressedKeysArray = keyState.GetPressedKeys(); foreach (Keys k in pressedKeysArray) if (!lastPressedKeys.Contains(k)) pressedKeys.Add(k); else lastPressedKeys.Remove(k); releasedKeys = lastPressedKeys; lastPressedKeys = new List(pressedKeysArray); // Get mouse button state. bool buttonPressed = mouseState.LeftButton == ButtonState.Pressed; /***** Begining of game logic. *****/ // Debug - allow user on this machine to direct input to any player's state in the game. if (pressedKeys.Contains(Keys.F1)) activePlayer = playerIdentifiers[0]; if (pressedKeys.Contains(Keys.F2)) activePlayer = playerIdentifiers[1]; if (pressedKeys.Contains(Keys.F3)) activePlayer = playerIdentifiers[2]; if (pressedKeys.Contains(Keys.F4)) activePlayer = playerIdentifiers[3]; // Debug - allow user on this machine to pause/resume game state advances. if (pressedKeys.Contains(Keys.F12) || pressedKeys.Contains(Keys.P) && (keyState.IsKeyDown(Keys.LeftControl) || keyState.IsKeyDown(Keys.RightControl))) { paused = !paused; return; // Don't update on pause start or stop } // Debug - automatically pause every 1000 frames. if (mGame.CurrentFrameNumber % 1000 == 0 && mGame.CurrentFrameNumber != lastAutoPause) { paused = true; lastAutoPause = mGame.CurrentFrameNumber; } //if (pressedKeys.Contains(Keys.Escape)) // this.Exit(); // Game update // Direct inputs to the game engine - only report changes. foreach (Keys k in pressedKeys) mGame.ApplyKeyInput(activePlayer, k, true); foreach (Keys k in releasedKeys) mGame.ApplyKeyInput(activePlayer, k, false); mGame.ApplyMouseLocationInput(activePlayer, mouseState.X, mouseState.Y); if (lastButtonPressed != buttonPressed) mGame.ApplyMouseButtonInput(activePlayer, buttonPressed); lastButtonPressed = buttonPressed; if (!paused) { // Advance the game engine. mGame.Update(mTargetTimeSpan); } } void DrawTestHarness(GameTime gameTime, SpriteBatch spriteBatch) { // BEGIN: Test harness stuff. if (paused && gameTime.TotalRealTime.Milliseconds < 500) spriteBatch.DrawString(font, "-=> Paused <=-", new Vector2(10, 130), Color.White); spriteBatch.DrawString(font, "Press [F1]...[F4] to simulate input for each player. Click X's to end game or terminate player.", new Vector2(10, 540), Color.White); spriteBatch.DrawString(font, "Press [ESC] to exit and [F12] to pause/unpause. Game auto-pauses every 1000 frames.", new Vector2(10, 570), Color.White); //END: Test harness stuff. } } }