FpsCounter.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // FpsCounter.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.Collections.Generic;
  12. using System.Diagnostics;
  13. using System.Text;
  14. using Microsoft.Xna.Framework;
  15. using Microsoft.Xna.Framework.Graphics;
  16. #endregion
  17. namespace PerformanceMeasuring.GameDebugTools
  18. {
  19. /// <summary>
  20. /// Component for FPS measure and draw.
  21. /// </summary>
  22. public class FpsCounter : DrawableGameComponent
  23. {
  24. #region Properties
  25. /// <summary>
  26. /// Gets current FPS
  27. /// </summary>
  28. public float Fps { get; private set; }
  29. /// <summary>
  30. /// Gets/Sets FPS sample duration.
  31. /// </summary>
  32. public TimeSpan SampleSpan { get; set; }
  33. #endregion
  34. #region Fields
  35. // Reference for debug manager.
  36. private DebugManager debugManager;
  37. // Stopwatch for fps measuring.
  38. private Stopwatch stopwatch;
  39. private int sampleFrames;
  40. // stringBuilder for FPS counter draw.
  41. private StringBuilder stringBuilder = new StringBuilder(16);
  42. #endregion
  43. #region Initialize
  44. public FpsCounter(Game game)
  45. : base(game)
  46. {
  47. SampleSpan = TimeSpan.FromSeconds(1);
  48. }
  49. public override void Initialize()
  50. {
  51. // Get debug manager from game service.
  52. debugManager =
  53. Game.Services.GetService(typeof(DebugManager)) as DebugManager;
  54. if (debugManager == null)
  55. throw new InvalidOperationException("DebugManaer is not registered.");
  56. // Register 'fps' command if debug command is registered as a service.
  57. IDebugCommandHost host =
  58. Game.Services.GetService(typeof(IDebugCommandHost))
  59. as IDebugCommandHost;
  60. if (host != null)
  61. {
  62. host.RegisterCommand("fps", "FPS Counter", this.CommandExecute);
  63. Visible = true;
  64. }
  65. // Initialize parameters.
  66. Fps = 0;
  67. sampleFrames = 0;
  68. stopwatch = Stopwatch.StartNew();
  69. stringBuilder.Length = 0;
  70. base.Initialize();
  71. }
  72. #endregion
  73. /// <summary>
  74. /// FPS command implementation.
  75. /// </summary>
  76. private void CommandExecute(IDebugCommandHost host,
  77. string command, IList<string> arguments)
  78. {
  79. if (arguments.Count == 0)
  80. Visible = !Visible;
  81. foreach (string arg in arguments)
  82. {
  83. switch (arg.ToLower())
  84. {
  85. case "on":
  86. Visible = true;
  87. break;
  88. case "off":
  89. Visible = false;
  90. break;
  91. }
  92. }
  93. }
  94. #region Update and Draw
  95. public override void Update(GameTime gameTime)
  96. {
  97. if (stopwatch.Elapsed > SampleSpan)
  98. {
  99. // Update FPS value and start next sampling period.
  100. Fps = (float)sampleFrames / (float)stopwatch.Elapsed.TotalSeconds;
  101. stopwatch.Reset();
  102. stopwatch.Start();
  103. sampleFrames = 0;
  104. // Update draw string.
  105. stringBuilder.Length = 0;
  106. stringBuilder.Append("FPS: ");
  107. stringBuilder.AppendNumber(Fps);
  108. }
  109. }
  110. public override void Draw(GameTime gameTime)
  111. {
  112. sampleFrames++;
  113. SpriteBatch spriteBatch = debugManager.SpriteBatch;
  114. SpriteFont font = debugManager.DebugFont;
  115. // Compute size of border area.
  116. Vector2 size = font.MeasureString("X");
  117. Rectangle rc =
  118. new Rectangle(0, 0, (int)(size.X * 14f), (int)(size.Y * 1.3f));
  119. Layout layout = new Layout(spriteBatch.GraphicsDevice.Viewport);
  120. rc = layout.Place(rc, 0.01f, 0.01f, Alignment.TopLeft);
  121. // Place FPS string in border area.
  122. size = font.MeasureString(stringBuilder);
  123. layout.ClientArea = rc;
  124. Vector2 pos = layout.Place(size, 0, 0.1f, Alignment.Center);
  125. // Draw
  126. spriteBatch.Begin();
  127. spriteBatch.Draw(debugManager.WhiteTexture, rc, new Color(0, 0, 0, 128));
  128. spriteBatch.DrawString(font, stringBuilder, pos, Color.White);
  129. spriteBatch.End();
  130. base.Draw(gameTime);
  131. }
  132. #endregion
  133. }
  134. }