GameplayScreen.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // GameplayScreen.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Threading;
  12. using Microsoft.Xna.Framework;
  13. using Microsoft.Xna.Framework.Content;
  14. using Microsoft.Xna.Framework.Graphics;
  15. using Microsoft.Xna.Framework.Input;
  16. using Microsoft.Xna.Framework.Net;
  17. #endregion
  18. namespace NetworkStateManagement
  19. {
  20. /// <summary>
  21. /// This screen implements the actual game logic. It is just a
  22. /// placeholder to get the idea across: you'll probably want to
  23. /// put some more interesting gameplay in here!
  24. /// </summary>
  25. class GameplayScreen : GameScreen
  26. {
  27. #region Fields
  28. NetworkSession networkSession;
  29. ContentManager content;
  30. SpriteFont gameFont;
  31. Vector2 playerPosition = new Vector2(100, 100);
  32. Vector2 enemyPosition = new Vector2(100, 100);
  33. Random random = new Random();
  34. float pauseAlpha;
  35. #endregion
  36. #region Properties
  37. /// <summary>
  38. /// The logic for deciding whether the game is paused depends on whether
  39. /// this is a networked or single player game. If we are in a network session,
  40. /// we should go on updating the game even when the user tabs away from us or
  41. /// brings up the pause menu, because even though the local player is not
  42. /// responding to input, other remote players may not be paused. In single
  43. /// player modes, however, we want everything to pause if the game loses focus.
  44. /// </summary>
  45. new bool IsActive
  46. {
  47. get
  48. {
  49. if (networkSession == null)
  50. {
  51. // Pause behavior for single player games.
  52. return base.IsActive;
  53. }
  54. else
  55. {
  56. // Pause behavior for networked games.
  57. return !IsExiting;
  58. }
  59. }
  60. }
  61. #endregion
  62. #region Initialization
  63. /// <summary>
  64. /// Constructor.
  65. /// </summary>
  66. public GameplayScreen(NetworkSession networkSession)
  67. {
  68. this.networkSession = networkSession;
  69. TransitionOnTime = TimeSpan.FromSeconds(1.5);
  70. TransitionOffTime = TimeSpan.FromSeconds(0.5);
  71. }
  72. /// <summary>
  73. /// Load graphics content for the game.
  74. /// </summary>
  75. public override void LoadContent()
  76. {
  77. if (content == null)
  78. content = new ContentManager(ScreenManager.Game.Services, "Content");
  79. gameFont = content.Load<SpriteFont>("gamefont");
  80. // A real game would probably have more content than this sample, so
  81. // it would take longer to load. We simulate that by delaying for a
  82. // while, giving you a chance to admire the beautiful loading screen.
  83. Thread.Sleep(1000);
  84. // once the load has finished, we use ResetElapsedTime to tell the game's
  85. // timing mechanism that we have just finished a very long frame, and that
  86. // it should not try to catch up.
  87. ScreenManager.Game.ResetElapsedTime();
  88. }
  89. /// <summary>
  90. /// Unload graphics content used by the game.
  91. /// </summary>
  92. public override void UnloadContent()
  93. {
  94. content.Unload();
  95. }
  96. #endregion
  97. #region Update and Draw
  98. /// <summary>
  99. /// Updates the state of the game.
  100. /// </summary>
  101. public override void Update(GameTime gameTime, bool otherScreenHasFocus,
  102. bool coveredByOtherScreen)
  103. {
  104. base.Update(gameTime, otherScreenHasFocus, false);
  105. // Gradually fade in or out depending on whether we are covered by the pause screen.
  106. if (coveredByOtherScreen)
  107. pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
  108. else
  109. pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);
  110. if (IsActive)
  111. {
  112. // Apply some random jitter to make the enemy move around.
  113. const float randomization = 10;
  114. enemyPosition.X += (float)(random.NextDouble() - 0.5) * randomization;
  115. enemyPosition.Y += (float)(random.NextDouble() - 0.5) * randomization;
  116. // Apply a stabilizing force to stop the enemy moving off the screen.
  117. Vector2 targetPosition = new Vector2(200, 200);
  118. enemyPosition = Vector2.Lerp(enemyPosition, targetPosition, 0.05f);
  119. // TODO: this game isn't very fun! You could probably improve
  120. // it by inserting something more interesting in this space :-)
  121. }
  122. // If we are in a network game, check if we should return to the lobby.
  123. if ((networkSession != null) && !IsExiting)
  124. {
  125. if (networkSession.SessionState == NetworkSessionState.Lobby)
  126. {
  127. LoadingScreen.Load(ScreenManager, true, null,
  128. new BackgroundScreen(),
  129. new LobbyScreen(networkSession));
  130. }
  131. }
  132. }
  133. /// <summary>
  134. /// Lets the game respond to player input. Unlike the Update method,
  135. /// this will only be called when the gameplay screen is active.
  136. /// </summary>
  137. public override void HandleInput(InputState input)
  138. {
  139. if (input == null)
  140. throw new ArgumentNullException("input");
  141. if (ControllingPlayer.HasValue)
  142. {
  143. // In single player games, handle input for the controlling player.
  144. HandlePlayerInput(input, ControllingPlayer.Value);
  145. }
  146. else if (networkSession != null)
  147. {
  148. // In network game modes, handle input for all the
  149. // local players who are participating in the session.
  150. foreach (LocalNetworkGamer gamer in networkSession.LocalGamers)
  151. {
  152. if (!HandlePlayerInput(input, gamer.SignedInGamer.PlayerIndex))
  153. break;
  154. }
  155. }
  156. }
  157. /// <summary>
  158. /// Handles input for the specified player. In local game modes, this is called
  159. /// just once for the controlling player. In network modes, it can be called
  160. /// more than once if there are multiple profiles playing on the local machine.
  161. /// Returns true if we should continue to handle input for subsequent players,
  162. /// or false if this player has paused the game.
  163. /// </summary>
  164. bool HandlePlayerInput(InputState input, PlayerIndex playerIndex)
  165. {
  166. // Look up inputs for the specified player profile.
  167. KeyboardState keyboardState = input.CurrentKeyboardStates[(int)playerIndex];
  168. GamePadState gamePadState = input.CurrentGamePadStates[(int)playerIndex];
  169. // The game pauses either if the user presses the pause button, or if
  170. // they unplug the active gamepad. This requires us to keep track of
  171. // whether a gamepad was ever plugged in, because we don't want to pause
  172. // on PC if they are playing with a keyboard and have no gamepad at all!
  173. bool gamePadDisconnected = !gamePadState.IsConnected &&
  174. input.GamePadWasConnected[(int)playerIndex];
  175. if (input.IsPauseGame(playerIndex) || gamePadDisconnected)
  176. {
  177. ScreenManager.AddScreen(new PauseMenuScreen(networkSession), playerIndex);
  178. return false;
  179. }
  180. // Otherwise move the player position.
  181. Vector2 movement = Vector2.Zero;
  182. if (keyboardState.IsKeyDown(Keys.Left))
  183. movement.X--;
  184. if (keyboardState.IsKeyDown(Keys.Right))
  185. movement.X++;
  186. if (keyboardState.IsKeyDown(Keys.Up))
  187. movement.Y--;
  188. if (keyboardState.IsKeyDown(Keys.Down))
  189. movement.Y++;
  190. Vector2 thumbstick = gamePadState.ThumbSticks.Left;
  191. movement.X += thumbstick.X;
  192. movement.Y -= thumbstick.Y;
  193. if (movement.Length() > 1)
  194. movement.Normalize();
  195. playerPosition += movement * 2;
  196. return true;
  197. }
  198. /// <summary>
  199. /// Draws the gameplay screen.
  200. /// </summary>
  201. public override void Draw(GameTime gameTime)
  202. {
  203. // This game has a blue background. Why? Because!
  204. ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
  205. Color.CornflowerBlue, 0, 0);
  206. // Our player and enemy are both actually just text strings.
  207. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  208. spriteBatch.Begin();
  209. spriteBatch.DrawString(gameFont, "// TODO", playerPosition, Color.Green);
  210. spriteBatch.DrawString(gameFont, "Insert Gameplay Here",
  211. enemyPosition, Color.DarkRed);
  212. if (networkSession != null)
  213. {
  214. string message = "Players: " + networkSession.AllGamers.Count;
  215. Vector2 messagePosition = new Vector2(100, 480);
  216. spriteBatch.DrawString(gameFont, message, messagePosition, Color.White);
  217. }
  218. spriteBatch.End();
  219. // If the game is transitioning on or off, fade it out to black.
  220. if (TransitionPosition > 0 || pauseAlpha > 0)
  221. {
  222. float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);
  223. ScreenManager.FadeBackBufferToBlack(alpha);
  224. }
  225. }
  226. #endregion
  227. }
  228. }