Considerations:
- You might change the namespace in line to your game's namespace.
- Currently, the game window's title will be used to display the framerate (this will change when XNA supports fonts). As a workaround, you can use garykac's bitmap fonts example to modify this behavior.
- If "Enabled" is set to false, framerates are not calculated (Current is set to 0).
- If "Visible" is set to false, the current framerate value is not displayed (but yet it can be calculated if enabled).
- When you want to show the decimal part of the framerate value (that is, "ShowDecimals" is set to true), you can set the display format to the fixed one (like "0.00").
- You can also set whether the time step must be fixed or not.
- You are free to modify/optimize the source code as desired. Please share your optimizations with the community.
Enjoy!!!
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Components;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
namespace WindowsGame1
{
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Components;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
namespace WindowsGame1
{
/// <summary>
/// Simple class to calculate the frame-per-seconds rate of your game.
/// </summary>
public sealed partial class Framerate : GameComponent
{
#region Constructors
/// <summary>
/// Parameterless constructor for this class.
/// </summary>
public Framerate()
{
#region Instance Methods
/// <summary>
/// Called when the gamecomponent needs to be updated.
/// </summary>
public override void Update()
{
/// <summary>
/// Called when the gamecomponent needs to be drawn.
/// </summary>
/// <remarks>
/// Currently, the framerate is shown in the window's title of the game.
/// </remarks>
public override void Draw()
{
}
}/// Simple class to calculate the frame-per-seconds rate of your game.
/// </summary>
public sealed partial class Framerate : GameComponent
{
#region Instance Fields
private float deltaFPSTime;
private double currentFramerate;
private string windowTitle, displayFormat;
private bool enabled, visible, canDraw, showDecimals;
#region Instance Properties
/// Gets or Sets a value to enable framerate calculation.
/// </summary>
public bool Enabled
{
get { return this.enabled; }
/// <summary>
/// Gets or Sets a value to display framerate on screen.
/// </summary>
/// <remarks>
/// Currently, the framerate is shown in the window's title of the game.
/// </remarks>
public bool Visible{
get { return this.visible; }
set
{
}
/// <summary>
/// Gets or sets a value indicating whether the time step must be fixed or not.
/// </summary>
/// <remarks>
/// If set to true, the game will target the desired constant framerate set in your main class ('Game1', by default).
/// </remarks>
public bool IsFixedTimeStep
{
/// <summary>
/// Gets or sets a value indicating whether the framerate will display decimals on screen or not.
/// </summary>
public bool ShowDecimals
{
/// <summary>
/// Gets or sets a value indicating whether the decimal part of the framerate value must be display as fixed format (or as double format, otherwise).
/// </summary>
/// <remarks>
/// The 'ShowDecimals' property must be set to true in order to set the proper format.
/// </remarks>
public bool FixedFormatDisplay
{
#endregion
/// <summary>
/// Gets the current framerate.
/// </summary>
/// <remarks>
/// The 'Enabled' property must have been set to true to retrieve values greater than zero.
/// </remarks>
public double Current
{
get{ return this.currentFramerate; }
}
/// <summary>
/// Gets or Sets a value to enable framerate calculation.
/// </summary>
public bool Enabled
{
get { return this.enabled; }
set
{
}{
this.enabled = value;
this.currentFramerate = 0;
if (this.Game != null && this.windowTitle != null && !this.enabled)
this.Game.Window.Title = this.windowTitle;
}this.currentFramerate = 0;
if (this.Game != null && this.windowTitle != null && !this.enabled)
this.Game.Window.Title = this.windowTitle;
/// <summary>
/// Gets or Sets a value to display framerate on screen.
/// </summary>
/// <remarks>
/// Currently, the framerate is shown in the window's title of the game.
/// </remarks>
public bool Visible{
get { return this.visible; }
set
{
this.visible = value;
if (this.Game != null && this.windowTitle != null && !this.visible)
this.Game.Window.Title = this.windowTitle;
}if (this.Game != null && this.windowTitle != null && !this.visible)
this.Game.Window.Title = this.windowTitle;
/// <summary>
/// Gets or sets a value indicating whether the time step must be fixed or not.
/// </summary>
/// <remarks>
/// If set to true, the game will target the desired constant framerate set in your main class ('Game1', by default).
/// </remarks>
public bool IsFixedTimeStep
{
get { return this.Game.IsFixedTimeStep; }
set
{
}set
{
if(this.Game != null)
}this.Game.IsFixedTimeStep = value;
/// <summary>
/// Gets or sets a value indicating whether the framerate will display decimals on screen or not.
/// </summary>
public bool ShowDecimals
{
get { return this.showDecimals; }
set { this.showDecimals = value; }
}set { this.showDecimals = value; }
/// <summary>
/// Gets or sets a value indicating whether the decimal part of the framerate value must be display as fixed format (or as double format, otherwise).
/// </summary>
/// <remarks>
/// The 'ShowDecimals' property must be set to true in order to set the proper format.
/// </remarks>
public bool FixedFormatDisplay
{
get { return this.displayFormat == "F"; }
set { this.displayFormat = value == true ? "F" : "R"; }
}set { this.displayFormat = value == true ? "F" : "R"; }
#endregion
#region Constructors
/// <summary>
/// Parameterless constructor for this class.
/// </summary>
public Framerate()
{
InitializeComponent();
} #endregion/// <summary>
/// Called after game initialization but before the first frame of the game.
/// </summary>
public override void Start()
{
this.canDraw = false;
this.currentFramerate = 0;
this.windowTitle = this.Game != null ? this.Game.Window.Title : String.Empty;
}/// <summary>
/// Called when the gamecomponent needs to be updated.
/// </summary>
public override void Update()
{
if (this.enabled)
{
}{
// The time since Update() method was last called.
float elapsed = (float)this.Game.ElapsedTime.TotalMilliseconds;
// Ads the elapsed time to the cumulative delta time.
this.deltaFPSTime += elapsed;
// If delta time is greater than a second: (a) the framerate is calculated, (b) it is marked to be drawn, and (c) the delta time is adjusted, accordingly.
if (this.deltaFPSTime > 1000)
{
}float elapsed = (float)this.Game.ElapsedTime.TotalMilliseconds;
// Ads the elapsed time to the cumulative delta time.
this.deltaFPSTime += elapsed;
// If delta time is greater than a second: (a) the framerate is calculated, (b) it is marked to be drawn, and (c) the delta time is adjusted, accordingly.
if (this.deltaFPSTime > 1000)
{
this.currentFramerate = 1000 / elapsed;
this.deltaFPSTime -= 1000;
this.canDraw = true;
}this.deltaFPSTime -= 1000;
this.canDraw = true;
/// <summary>
/// Called when the gamecomponent needs to be drawn.
/// </summary>
/// <remarks>
/// Currently, the framerate is shown in the window's title of the game.
/// </remarks>
public override void Draw()
{
// If the framerate can be drawn, it is shown in the window's title of
the game.
if (this.visible && this.canDraw)
{
} #endregionthe game.
if (this.visible && this.canDraw)
{
string currentFramerateString = this.showDecimals ? this.currentFramerate.ToString(this.displayFormat) : ((int)this.currentFramerate).ToString("D");
this.Game.Window.Title = "FPS: " + currentFramerateString;
this.canDraw = false;
}this.Game.Window.Title = "FPS: " + currentFramerateString;
this.canDraw = false;
[We will discuss and focus on XNA GSE later.]
great! I enjoy this component. thank you!
ReplyDeleteThis is not very accurate framerate counter...
ReplyDeleteThis component was created for the first beta of XNA GSE. You'd better use this one instead:
ReplyDeletehttp://blogs.msdn.com/shawnhar/archive/2007/06/08/displaying-the-framerate.aspx
I guess we've found why every framerate counter wasn't that accurate on XNA v1 ...
ReplyDeletehttp://blogs.msdn.com/shawnhar/archive/2007/11/23/game-timing-in-xna-game-studio-2-0.aspx