Frame rate or FPS, how it is most commonly known is a way for you to know how many images per second is you game drawing. The more the better. Less then 30 and you start to see hiccups.
So how can you measure your frame rate in XNA?
Inside your game1 class declare these vars:
SpriteFont _spr_font; int _total_frames = 0; float _elapsed_time = 0.0f; int _fps = 0; |
On function LoadContent() do
// Put the name of the font _spr_font = Content.Load("kootenay"); you have on your project |
On the update pump do:
protected override void Update(GameTime gameTime) { // Update _elapsed_time += (float)gameTime.ElapsedGameTime.TotalMilliseconds; // 1 Second has passed if (_elapsed_time >= 1000.0f) { _fps = _total_frames; _total_frames = 0; _elapsed_time = 0; } // Allows the game to exit if (Keyboard.GetState().IsKeyDown(Keys.Escape)) this.Exit(); base.Update(gameTime); } |
Finally on Draw function do:
protected override void Draw(GameTime gameTime) { // Only update total frames when drawing _total_frames++; GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.DrawString(_spr_font, string.Format("FPS={0}", _fps), new Vector2(10.0f, 20.0f), Color.White); spriteBatch.End(); base.Draw(gameTime); } |
If everything went alright you should have a white counter on the upper left screen. You probably want to turn this into a drawable component or adjusting it to be an independent component on your engine.
Here’s the project for VC# Express : download
note: For those who have asked me why do I use a prefix _ on some variables. I use this to help me know which vars are members of the class and which aren’t. I don’t like using mPosition, instead I use _Position.
if (_elapsed_time >= 1000.0f)
Does not works wiht C# XNA 4.0 – what means > ? Even when i remove this > i get compiler error, cant convert typ float into bool. Any idea? thx
Thorsten, the > thing is a HTML code – and it got there simply because you copied and pasted from this website. Just replace it with a > symbol.
Or you could be a real G and just write:
spriteBatch.DrawString(font, “FPS: ” + (1000 / gameTime.ElapsedGameTime.Milliseconds), position, Color.White);
Thanks for sharing.
string.Format(“FPS={0}”, _fps) will create garbage.
Better to update a StringBuilder perhaps. A tiny point, but relevant knowledge for a tut.
Thanks for the tuts. good reads.
public struct stringbuilderHolder
{
public StringBuilder sb;// = new StringBuilder();
private string __holder_string_so_not_touch;
public stringbuilderHolder(int stringBuilderImmutableSize)
{
// 32 , 32 was the default.
sb = new StringBuilder(stringBuilderImmutableSize, stringBuilderImmutableSize);
__holder_string_so_not_touch = (string)sb.GetType().GetField(
“m_StringValue”, BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(sb);
}
public void empty()
{
if (sb.Length > 1)
{
sb.Remove(0, sb.Length);
}
}
}
then in your class
#if DEBUG
public static stringbuilderHolder screenOutputStringbuilder;
#endif
then in Update()
#if DEBUG
// Update
DebugParams._elapsed_time += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
// 1 Second has passed
if (DebugParams._elapsed_time >= 1000.0f)
{
DebugParams._fps = DebugParams._total_frames;
DebugParams._total_frames = 0;
DebugParams._elapsed_time = 0;
}
// clean out the stringbuilder; regardless of how full it is we always just “remove” on it.
// NOTICE WE CALL IT ON THE STRUCT NOT THE STRINGBUILDER
screenDebugOutputStringbuilder.empty();
// use the Screen Output Stringbuilder for something
screenDebugOutputStringbuilder.sb.ConcatFormat(“FPS={0}”, DebugParams._fps);
#endif
And finally in Draw()
#if DEBUG
DebugParams._total_frames++;
spriteBatch.DrawString(font, screenDebugOutputStringbuilder.sb, DebugParams.DebugTextLocation , Color.White);
// Only update total frames when drawing
#endif
props to http://www.gavpugh.com/xnac-articles/
Zero Garbage. Hope it helps someone else.
public struct DebugParams
{
public static Vector2 DebugTextLocation;
public static void InitializeTitleSafeArea(GraphicsDevice GraphicsDevice)
{
DebugTextLocation = new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y);
}
public static int _total_frames = 0;
public static float _elapsed_time = 0.0f;
public static int _fps = 0;
}
Just to keep my life simple.