Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Here is how I do it and with this method:</p> <ul> <li>You average over n Frames</li> <li>You can use it with any initialization method you choose</li> <li>It should be easy to read and follow</li> </ul> <pre class="lang-cs prettyprint-override"><code>using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; namespace _60fps { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; SpriteFont OutputFont; float Fps = 0f; private const int NumberSamples = 50; //Update fps timer based on this number of samples int[] Samples = new int[NumberSamples]; int CurrentSample = 0; int TicksAggregate = 0; int SecondSinceStart = 0; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { base.Initialize(); graphics.SynchronizeWithVerticalRetrace = false; int DesiredFrameRate = 60; TargetElapsedTime = new TimeSpan(TimeSpan.TicksPerSecond / DesiredFrameRate); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); OutputFont = Content.Load&lt;SpriteFont&gt;("MessageFont"); } protected override void UnloadContent() {/* Nothing to do */} protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Escape)) this.Exit(); base.Update(gameTime); } private float Sum(int[] Samples) { float RetVal = 0f; for (int i = 0; i &lt; Samples.Length; i++) { RetVal += (float)Samples[i]; } return RetVal; } private Color ClearColor = Color.FromNonPremultiplied(20, 20, 40, 255); protected override void Draw(GameTime gameTime) { Samples[CurrentSample++] = (int)gameTime.ElapsedGameTime.Ticks; TicksAggregate += (int)gameTime.ElapsedGameTime.Ticks; if (TicksAggregate &gt; TimeSpan.TicksPerSecond) { TicksAggregate -= (int)TimeSpan.TicksPerSecond; SecondSinceStart += 1; } if (CurrentSample == NumberSamples) //We are past the end of the array since the array is 0-based and NumberSamples is 1-based { float AverageFrameTime = Sum(Samples) / NumberSamples; Fps = TimeSpan.TicksPerSecond / AverageFrameTime; CurrentSample = 0; } GraphicsDevice.Clear(ClearColor); spriteBatch.Begin(); if (Fps &gt; 0) { spriteBatch.DrawString(OutputFont, string.Format("Current FPS: {0}\r\nTime since startup: {1}", Fps.ToString("000"), TimeSpan.FromSeconds(SecondSinceStart).ToString()), new Vector2(10,10), Color.White); } spriteBatch.End(); base.Draw(gameTime); } } } </code></pre> <p>As for: "but the question why displayed FPS was changing more often than once a second is still open"</p> <p>The difference between ElapsedGameTime and ElapsedRealTime is that "ElapsedGameTime" is the amount of time since the last time you entered the Update or Draw statement (depending on which "gameTime" you're using - the one from Update or the one from Draw).</p> <p>ElapsedRealTime is the time since the game started. Because of this, it increases linearly as the game continues to run. Indeed, after 1 second, you'll update every frame because your logic looked like this:</p> <p>(Let's assume you were running 4 fps for the sake of easy explanation):</p> <ul> <li>Frame 1: ElapsedRealTime: 0.25. Running total now: 0.25</li> <li>Frame 2: ElapsedRealTime: 0.5 Running total now: 0.75</li> <li>Frame 3: ElapsedRealTime: 0.75 Running total now: 1.5</li> <li>Running total greater than 1!!! Show FPS!</li> <li>Set Running total = 0</li> <li>Frame 4: ElapsedRealTime: 1.00 Running total now: 1.0</li> <li>Running total greater than 1!!! Show FPS!</li> </ul> <p>Now that you've fixed the counter, you should now only be getting Elapsed Game Time changes of a steady 0.25 so the progression now moves:</p> <ul> <li>Frame 1: ElapsedGameTime: 0.25. Running total now: 0.25</li> <li>Frame 2: ElapsedGameTime: 0.25 Running total now: 0.50</li> <li>Frame 3: ElapsedGameTime: 0.25 Running total now: 0.75</li> <li>Frame 4: ElapsedGameTime: 0.25 Running total now: 1.00</li> <li>Running total greater than 1!!! Show FPS!</li> <li><p>Set Running total = 0</p></li> <li><p>Frame 5: ElapsedGameTime: 0.25. Running total now: 0.25</p></li> <li>Frame 6: ElapsedGameTime: 0.25 Running total now: 0.50</li> <li>Frame 7: ElapsedGameTime: 0.25 Running total now: 0.75</li> <li>Frame 8: ElapsedGameTime: 0.25 Running total now: 1.00</li> <li>Running total greater than 1!!! Show FPS!</li> <li>Set Running total = 0</li> </ul> <p>Which is what you're expecting. In short, now that you corrected the first problem, you should have corrected the second too and "why" is explained above.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload