Omer Eliyahu
Omer Eliyahu

Reputation: 19

XNA 4.0 C# limit FPS

I'm trying to limit the 'frames per second' of my Monogame XNA project, but my limitFrames function is inaccurate.

For example, My project is running on 60 fps without a limiter. But when I'm using the limiter and setting up the frameRateLimiter variable to 30 frames per second, the project's max fps is around 27.

Can someone figure the solution for it?

Frames Limiter Code

private float frameRateLimiter = 30f;
// ...

protected override void Draw(GameTime gameTime)
{
    float startDrawTime = gameTime.TotalGameTime.Milliseconds;
    limitFrames(startDrawTime, gameTime);
    base.Draw(gameTime);
}

private void limitFrames(float startDrawTime, GameTime gameTime)
{
    float durationTime = startDrawTime - gameTime.TotalGameTime.Milliseconds;
    // FRAME LIMITER
    if (frameRateLimiter != 0)
    {
        if (durationTime < (1000f / frameRateLimiter))
        {
            // *THE INACCERACY IS MIGHT COMING FROM THIS LINE*
            System.Threading.Thread.Sleep((int)((1000f / frameRateLimiter) - durationTime));
        }
     }
}

Frames Per Second Shower

public class FramesPerSecond
{
    // The FPS
    public float FPS;

    // Variables that help for the calculation of the FPS
    private int currentFrame;
    private float currentTime;
    private float prevTime;
    private float timeDiffrence;
    private float FrameTimeAverage;
    private float[] frames_sample;
    const int NUM_SAMPLES = 20;

    public FramesPerSecond()
    {
        this.FPS = 0;
        this.frames_sample = new float[NUM_SAMPLES];
        this.prevTime = 0;
    }

    public void Update(GameTime gameTime)
    {
        this.currentTime = (float)gameTime.TotalGameTime.TotalMilliseconds;
        this.timeDiffrence = currentTime - prevTime;
        this.frames_sample[currentFrame % NUM_SAMPLES] = timeDiffrence;
        int count;
        if (this.currentFrame < NUM_SAMPLES)
        {
            count = currentFrame;
        }
        else
        {
            count = NUM_SAMPLES;
        }
        if (this.currentFrame % NUM_SAMPLES == 0)
        {
            this.FrameTimeAverage = 0;
            for (int i = 0; i < count; i++)
            {
                this.FrameTimeAverage += this.frames_sample[i];
            }
            if (count != 0)
            {
                this.FrameTimeAverage /= count;
            }
            if (this.FrameTimeAverage > 0)
            {
                this.FPS = (1000f / this.FrameTimeAverage);
            }
            else
            {
                this.FPS = 0;
            }
        }
        this.currentFrame++;
        this.prevTime = this.currentTime;
}

Upvotes: 0

Views: 2496

Answers (1)

absoluteAquarian
absoluteAquarian

Reputation: 506

You don't need to re-invent the wheel.

MonoGame and XNA already have built-in variables that handle this for you.

To limit the framerate to a maximum of 30fps, set IsFixedTimeStep and TargetElapsedTime to the following in your Initialize() method:

IsFixedTimeStep = true;  //Force the game to update at fixed time intervals
TargetElapsedTime = TimeSpan.FromSeconds(1 / 30.0f);  //Set the time interval to 1/30th of a second

The FPS of your game can be evaluated using:

//"gameTime" is of type GameTime
float fps = 1f / gameTime.ElapsedGameTime.TotalSeconds;

Upvotes: 5

Related Questions