NetworkBusyScreen.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. //-----------------------------------------------------------------------------
  2. // NetworkBusyScreen.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using Microsoft.Xna.Framework;
  9. using Microsoft.Xna.Framework.Content;
  10. using Microsoft.Xna.Framework.Graphics;
  11. namespace NetworkStateManagement
  12. {
  13. /// <summary>
  14. /// When an asynchronous network operation (for instance searching for or joining a
  15. /// session) is in progress, we want to display some sort of busy indicator to let
  16. /// the user know the game hasn't just locked up. We also want to make sure they
  17. /// can't pick some other menu option before the current operation has finished.
  18. /// This screen takes care of both requirements in a single stroke. It monitors
  19. /// the IAsyncResult returned by an asynchronous network call, displaying a busy
  20. /// indicator for as long as the call is still in progress. When it notices the
  21. /// IAsyncResult has completed, it raises an event to let the game know it should
  22. /// proceed to the next step, after which the busy screen automatically goes away.
  23. /// Because this screen is on top of all others for as long as the asynchronous
  24. /// operation is in progress, it automatically takes over all user input,
  25. /// preventing any other menu entries being selected until the operation completes.
  26. /// </summary>
  27. class NetworkBusyScreen : GameScreen
  28. {
  29. IAsyncResult asyncResult;
  30. Texture2D gradientTexture;
  31. Texture2D catTexture;
  32. public event EventHandler<OperationCompletedEventArgs> OperationCompleted;
  33. /// <summary>
  34. /// Constructs a network busy screen for the specified asynchronous operation.
  35. /// </summary>
  36. public NetworkBusyScreen(IAsyncResult asyncResult)
  37. {
  38. this.asyncResult = asyncResult;
  39. IsPopup = true;
  40. TransitionOnTime = TimeSpan.FromSeconds(0.1);
  41. TransitionOffTime = TimeSpan.FromSeconds(0.2);
  42. }
  43. /// <summary>
  44. /// Loads graphics content for this screen. This uses the shared ContentManager
  45. /// provided by the Game class, so the content will remain loaded forever.
  46. /// Whenever a subsequent NetworkBusyScreen tries to load this same content,
  47. /// it will just get back another reference to the already loaded data.
  48. /// </summary>
  49. public override void LoadContent()
  50. {
  51. ContentManager content = ScreenManager.Game.Content;
  52. gradientTexture = content.Load<Texture2D>("gradient");
  53. catTexture = content.Load<Texture2D>("cat");
  54. }
  55. /// <summary>
  56. /// Updates the NetworkBusyScreen.
  57. /// </summary>
  58. public override void Update(GameTime gameTime, bool otherScreenHasFocus,
  59. bool coveredByOtherScreen)
  60. {
  61. base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
  62. // Has our asynchronous operation completed?
  63. if ((asyncResult != null) && asyncResult.IsCompleted)
  64. {
  65. // If so, raise the OperationCompleted event.
  66. if (OperationCompleted != null)
  67. {
  68. OperationCompleted(this,
  69. new OperationCompletedEventArgs(asyncResult));
  70. }
  71. ExitScreen();
  72. asyncResult = null;
  73. }
  74. }
  75. /// <summary>
  76. /// Draws the NetworkBusyScreen.
  77. /// </summary>
  78. public override void Draw(GameTime gameTime)
  79. {
  80. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  81. SpriteFont font = ScreenManager.Font;
  82. string message = Resources.NetworkBusy;
  83. const int hPad = 32;
  84. const int vPad = 16;
  85. // Center the message text in the viewport.
  86. Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
  87. Vector2 viewportSize = new Vector2(viewport.Width, viewport.Height);
  88. Vector2 textSize = font.MeasureString(message);
  89. // Add enough room to spin a cat.
  90. Vector2 catSize = new Vector2(catTexture.Width);
  91. textSize.X = Math.Max(textSize.X, catSize.X);
  92. textSize.Y += catSize.Y + vPad;
  93. Vector2 textPosition = (viewportSize - textSize) / 2;
  94. // The background includes a border somewhat larger than the text itself.
  95. Rectangle backgroundRectangle = new Rectangle((int)textPosition.X - hPad,
  96. (int)textPosition.Y - vPad,
  97. (int)textSize.X + hPad * 2,
  98. (int)textSize.Y + vPad * 2);
  99. // Fade the popup alpha during transitions.
  100. Color color = Color.White * TransitionAlpha;
  101. spriteBatch.Begin();
  102. // Draw the background rectangle.
  103. spriteBatch.Draw(gradientTexture, backgroundRectangle, color);
  104. // Draw the message box text.
  105. spriteBatch.DrawString(font, message, textPosition, color);
  106. // Draw the spinning cat progress indicator.
  107. float catRotation = (float)gameTime.TotalGameTime.TotalSeconds * 3;
  108. Vector2 catPosition = new Vector2(textPosition.X + textSize.X / 2,
  109. textPosition.Y + textSize.Y -
  110. catSize.Y / 2);
  111. spriteBatch.Draw(catTexture, catPosition, null, color, catRotation,
  112. catSize / 2, 1, SpriteEffects.None, 0);
  113. spriteBatch.End();
  114. }
  115. }
  116. }