#region File Description
//-----------------------------------------------------------------------------
// FpsCounter.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
#endregion
namespace HoneycombRush.GameDebugTools
{
///
/// Component for FPS measure and draw.
///
public class FpsCounter : DrawableGameComponent
{
#region Properties
///
/// Gets current FPS
///
public float Fps { get; private set; }
///
/// Gets/Sets FPS sample duration.
///
public TimeSpan SampleSpan { get; set; }
#endregion
#region Fields
// Reference for debug manager.
private DebugManager debugManager;
// Stopwatch for fps measuring.
private Stopwatch stopwatch;
private int sampleFrames;
// stringBuilder for FPS counter draw.
private StringBuilder stringBuilder = new StringBuilder(16);
#endregion
#region Initialize
public FpsCounter(Game game)
: base(game)
{
SampleSpan = TimeSpan.FromSeconds(1);
}
public override void Initialize()
{
DrawOrder = int.MaxValue - 1;
// Get debug manager from game service.
debugManager =
Game.Services.GetService(typeof(DebugManager)) as DebugManager;
if (debugManager == null)
throw new InvalidOperationException("DebugManaer is not registered.");
// Register 'fps' command if debug command is registered as a service.
IDebugCommandHost host =
Game.Services.GetService(typeof(IDebugCommandHost))
as IDebugCommandHost;
if (host != null)
{
host.RegisterCommand("fps", "FPS Counter", this.CommandExecute);
Visible = false;
}
// Initialize parameters.
Fps = 0;
sampleFrames = 0;
stopwatch = Stopwatch.StartNew();
stringBuilder.Length = 0;
base.Initialize();
}
#endregion
///
/// FPS command implementation.
///
private void CommandExecute(IDebugCommandHost host,
string command, IList arguments)
{
if (arguments.Count == 0)
Visible = !Visible;
foreach (string arg in arguments)
{
switch (arg.ToLower())
{
case "on":
Visible = true;
break;
case "off":
Visible = false;
break;
}
}
}
#region Update and Draw
public override void Update(GameTime gameTime)
{
if (stopwatch.Elapsed > SampleSpan)
{
// Update FPS value and start next sampling period.
Fps = (float)sampleFrames / (float)stopwatch.Elapsed.TotalSeconds;
stopwatch.Reset();
stopwatch.Start();
sampleFrames = 0;
// Update draw string.
stringBuilder.Length = 0;
stringBuilder.Append("FPS: ");
stringBuilder.AppendNumber(Fps);
}
}
public override void Draw(GameTime gameTime)
{
sampleFrames++;
SpriteBatch spriteBatch = debugManager.SpriteBatch;
SpriteFont font = debugManager.DebugFont;
// Compute size of border area.
Vector2 size = font.MeasureString("X");
Rectangle rc =
new Rectangle(0, 0, (int)(size.X * 14f), (int)(size.Y * 1.3f));
Layout layout = new Layout(spriteBatch.GraphicsDevice.Viewport);
rc = layout.Place(rc, 0.01f, 0.01f, Alignment.TopLeft);
// Place FPS string in border area.
size = font.MeasureString(stringBuilder);
layout.ClientArea = rc;
Vector2 pos = layout.Place(size, 0, 0.1f, Alignment.Center);
// Draw
spriteBatch.Begin();
spriteBatch.Draw(debugManager.WhiteTexture, rc, new Color(0, 0, 0, 128));
spriteBatch.DrawString(font, stringBuilder, pos, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
#endregion
}
}