MessageDisplayComponent.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. //-----------------------------------------------------------------------------
  2. // MessageDisplayComponent.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using System.Collections.Generic;
  9. using Microsoft.Xna.Framework;
  10. using Microsoft.Xna.Framework.Graphics;
  11. namespace CatapultGame
  12. {
  13. /// <summary>
  14. /// Component implements the IMessageDisplay interface. This is used to show
  15. /// notification messages when interesting events occur, for instance when
  16. /// gamers join or leave the network session
  17. /// </summary>
  18. class MessageDisplayComponent : DrawableGameComponent, IMessageDisplay
  19. {
  20. SpriteBatch spriteBatch;
  21. SpriteFont font;
  22. // List of the currently visible notification messages.
  23. List<NotificationMessage> messages = new List<NotificationMessage>();
  24. // Coordinates threadsafe access to the message list.
  25. object syncObject = new object();
  26. // Tweakable settings control how long each message is visible.
  27. static readonly TimeSpan fadeInTime = TimeSpan.FromSeconds(0.25);
  28. static readonly TimeSpan showTime = TimeSpan.FromSeconds(5);
  29. static readonly TimeSpan fadeOutTime = TimeSpan.FromSeconds(0.5);
  30. CatapultGame game;
  31. /// <summary>
  32. /// Constructs a new message display component.
  33. /// </summary>
  34. public MessageDisplayComponent(Game game)
  35. : base(game)
  36. {
  37. this.game = game as CatapultGame;
  38. // Register ourselves to implement the IMessageDisplay service.
  39. game.Services.AddService(typeof(IMessageDisplay), this);
  40. }
  41. /// <summary>
  42. /// Load graphics content for the message display.
  43. /// </summary>
  44. protected override void LoadContent()
  45. {
  46. spriteBatch = new SpriteBatch(GraphicsDevice);
  47. //font = Game.Content.Load<SpriteFont>("menufont");
  48. font = Game.Content.Load<SpriteFont>("Fonts/MenuFont");
  49. }
  50. /// <summary>
  51. /// Updates the message display component.
  52. /// </summary>
  53. public override void Update(GameTime gameTime)
  54. {
  55. lock (syncObject)
  56. {
  57. int index = 0;
  58. float targetPosition = 0;
  59. // Update each message in turn.
  60. while (index < messages.Count)
  61. {
  62. NotificationMessage message = messages[index];
  63. // Gradually slide the message toward its desired position.
  64. float positionDelta = targetPosition - message.Position;
  65. float velocity = (float)gameTime.ElapsedGameTime.TotalSeconds * 2;
  66. message.Position += positionDelta * Math.Min(velocity, 1);
  67. // Update the age of the message.
  68. message.Age += gameTime.ElapsedGameTime;
  69. if (message.Age < showTime + fadeOutTime)
  70. {
  71. // This message is still alive.
  72. index++;
  73. // Any subsequent messages should be positioned below
  74. // this one, unless it has started to fade out.
  75. if (message.Age < showTime)
  76. targetPosition++;
  77. }
  78. else
  79. {
  80. // This message is old, and should be removed.
  81. messages.RemoveAt(index);
  82. }
  83. }
  84. }
  85. }
  86. /// <summary>
  87. /// Draws the message display component.
  88. /// </summary>
  89. public override void Draw(GameTime gameTime)
  90. {
  91. lock (syncObject)
  92. {
  93. // Early out if there are no messages to display.
  94. if (messages.Count == 0)
  95. return;
  96. Vector2 position = new Vector2(ScreenManager.BASE_BUFFER_WIDTH - 100, 0);
  97. spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, game.ScreenManager.GlobalTransformation);
  98. // Draw each message in turn.
  99. foreach (NotificationMessage message in messages)
  100. {
  101. const float scale = 0.75f;
  102. // Compute the alpha of this message.
  103. float alpha = 1;
  104. if (message.Age < fadeInTime)
  105. {
  106. // Fading in.
  107. alpha = (float)(message.Age.TotalSeconds /
  108. fadeInTime.TotalSeconds);
  109. }
  110. else if (message.Age > showTime)
  111. {
  112. // Fading out.
  113. TimeSpan fadeOut = showTime + fadeOutTime - message.Age;
  114. alpha = (float)(fadeOut.TotalSeconds /
  115. fadeOutTime.TotalSeconds);
  116. }
  117. // Compute the message position.
  118. position.Y = 80 + message.Position * font.LineSpacing * scale;
  119. // Compute an origin value to right align each message.
  120. Vector2 origin = font.MeasureString(message.Text);
  121. origin.Y = 0;
  122. // Draw the message text, with a drop shadow.
  123. spriteBatch.DrawString(font, message.Text, position + Vector2.One,
  124. Color.Black * alpha, 0,
  125. origin, scale, SpriteEffects.None, 0);
  126. spriteBatch.DrawString(font, message.Text, position,
  127. Color.White * alpha, 0,
  128. origin, scale, SpriteEffects.None, 0);
  129. }
  130. spriteBatch.End();
  131. }
  132. }
  133. /// <summary>
  134. /// Shows a new notification message.
  135. /// </summary>
  136. public void ShowMessage(string message, params object[] parameters)
  137. {
  138. string formattedMessage = string.Format(message, parameters);
  139. lock (syncObject)
  140. {
  141. float startPosition = messages.Count;
  142. messages.Add(new NotificationMessage(formattedMessage, startPosition));
  143. }
  144. }
  145. /// <summary>
  146. /// Helper class stores the position and text of a single notification message.
  147. /// </summary>
  148. class NotificationMessage
  149. {
  150. public string Text;
  151. public float Position;
  152. public TimeSpan Age;
  153. public NotificationMessage(string text, float position)
  154. {
  155. Text = text;
  156. Position = position;
  157. Age = TimeSpan.Zero;
  158. }
  159. }
  160. }
  161. }