NetworkBusyScreen.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // NetworkBusyScreen.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 Microsoft.Xna.Framework;
  12. using Microsoft.Xna.Framework.Content;
  13. using Microsoft.Xna.Framework.Graphics;
  14. #endregion
  15. namespace NetRumble
  16. {
  17. /// <summary>
  18. /// When an asynchronous network operation (for instance searching for or joining a
  19. /// session) is in progress, we want to display some sort of busy indicator to let
  20. /// the user know the game hasn't just locked up. We also want to make sure they
  21. /// can't pick some other menu option before the current operation has finished.
  22. /// This screen takes care of both requirements in a single stroke. It monitors
  23. /// the IAsyncResult returned by an asynchronous network call, displaying a busy
  24. /// indicator for as long as the call is still in progress. When it notices the
  25. /// IAsyncResult has completed, it raises an event to let the game know it should
  26. /// proceed to the next step, after which the busy screen automatically goes away.
  27. /// Because this screen is on top of all others for as long as the asynchronous
  28. /// operation is in progress, it automatically takes over all user input,
  29. /// preventing any other menu entries being selected until the operation completes.
  30. /// </summary>
  31. /// <remarks>Based on a class in the Network Game State Management sample.</remarks>
  32. class NetworkBusyScreen : GameScreen
  33. {
  34. #region Constants
  35. const float busyTextureScale = 0.8f;
  36. #endregion
  37. #region Fields
  38. /// <summary>
  39. /// The message displayed in the screen.
  40. /// </summary>
  41. string message;
  42. /// <summary>
  43. /// The async result polled by the screen.
  44. /// </summary>
  45. IAsyncResult asyncResult;
  46. /// <summary>
  47. /// The rotating "activity" texture in the screen.
  48. /// </summary>
  49. Texture2D busyTexture;
  50. #endregion
  51. #region Events
  52. public event EventHandler<OperationCompletedEventArgs> OperationCompleted;
  53. #endregion
  54. #region Initialization
  55. /// <summary>
  56. /// Constructs a network busy screen for the specified asynchronous operation.
  57. /// </summary>
  58. public NetworkBusyScreen(string message, IAsyncResult asyncResult)
  59. {
  60. this.message = message;
  61. this.asyncResult = asyncResult;
  62. IsPopup = true;
  63. TransitionOnTime = TimeSpan.FromSeconds(0.1);
  64. TransitionOffTime = TimeSpan.FromSeconds(0.2);
  65. }
  66. /// <summary>
  67. /// Loads graphics content for this screen. This uses the shared ContentManager
  68. /// provided by the Game class, so the content will remain loaded forever.
  69. /// Whenever a subsequent NetworkBusyScreen tries to load this same content,
  70. /// it will just get back another reference to the already loaded data.
  71. /// </summary>
  72. public override void LoadContent()
  73. {
  74. ContentManager content = ScreenManager.Game.Content;
  75. busyTexture = content.Load<Texture2D>("Textures/chatTalking");
  76. }
  77. #endregion
  78. #region Update and Draw
  79. /// <summary>
  80. /// Updates the NetworkBusyScreen.
  81. /// </summary>
  82. public override void Update(GameTime gameTime, bool otherScreenHasFocus,
  83. bool coveredByOtherScreen)
  84. {
  85. base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
  86. // Has our asynchronous operation completed?
  87. if ((asyncResult != null) && asyncResult.IsCompleted)
  88. {
  89. // If so, raise the OperationCompleted event.
  90. if (OperationCompleted != null)
  91. {
  92. OperationCompleted(this,
  93. new OperationCompletedEventArgs(asyncResult));
  94. }
  95. ExitScreen();
  96. asyncResult = null;
  97. }
  98. }
  99. /// <summary>
  100. /// Draws the NetworkBusyScreen.
  101. /// </summary>
  102. public override void Draw(GameTime gameTime)
  103. {
  104. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  105. SpriteFont font = ScreenManager.Font;
  106. const int hPad = 32;
  107. const int vPad = 16;
  108. // Center the message text in the viewport.
  109. Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
  110. Vector2 viewportSize = new Vector2(viewport.Width, viewport.Height);
  111. Vector2 textSize = font.MeasureString(message);
  112. // Add enough room to spin a texture.
  113. Vector2 busyTextureSize = new Vector2(busyTexture.Width * busyTextureScale);
  114. Vector2 busyTextureOrigin = new Vector2(busyTexture.Width / 2,
  115. busyTexture.Height / 2);
  116. textSize.X = Math.Max(textSize.X, busyTextureSize.X);
  117. textSize.Y += busyTextureSize.Y + vPad;
  118. Vector2 textPosition = (viewportSize - textSize) / 2;
  119. // The background includes a border somewhat larger than the text itself.
  120. Rectangle backgroundRectangle = new Rectangle((int)textPosition.X - hPad,
  121. (int)textPosition.Y - vPad,
  122. (int)textSize.X + hPad * 2,
  123. (int)textSize.Y + vPad * 2);
  124. // Fade the popup alpha during transitions.
  125. Color color = new Color(255, 255, 255, TransitionAlpha);
  126. // Draw the background rectangle.
  127. Rectangle backgroundRectangle2 = new Rectangle(backgroundRectangle.X - 1,
  128. backgroundRectangle.Y - 1, backgroundRectangle.Width + 2,
  129. backgroundRectangle.Height + 2);
  130. ScreenManager.DrawRectangle(backgroundRectangle2, new Color(128, 128, 128,
  131. (byte)(192.0f * (float)TransitionAlpha / 255.0f)));
  132. ScreenManager.DrawRectangle(backgroundRectangle, new Color(0, 0, 0,
  133. (byte)(232.0f * (float)TransitionAlpha / 255.0f)));
  134. //spriteBatch.Begin(0,BlendState.NonPremultiplied, null, null, null);
  135. spriteBatch.Begin();
  136. // Draw the message box text.
  137. spriteBatch.DrawString(font, message, textPosition, color);
  138. // Draw the spinning cat progress indicator.
  139. float busyTextureRotation = (float)gameTime.TotalGameTime.TotalSeconds * 3;
  140. Vector2 busyTexturePosition = new Vector2(textPosition.X + textSize.X / 2,
  141. textPosition.Y + textSize.Y - busyTextureSize.Y / 2);
  142. spriteBatch.Draw(busyTexture, busyTexturePosition, null, color,
  143. busyTextureRotation, busyTextureOrigin, busyTextureScale,
  144. SpriteEffects.None, 0);
  145. spriteBatch.End();
  146. }
  147. #endregion
  148. }
  149. }