簡體   English   中英

XNA / MonoGame:獲取每秒幀數

[英]XNA/MonoGame: Getting the Frames Per Second

我試圖獲得我游戲的當前FPS,但是我只能找到每秒更新FPS變量的方法。 例如https://github.com/CartBlanche/MonoGame-Samples/blob/master/Draw2D/FPSCounterComponent.cshttp://www.david-amador.com/2009/11/how-to-do-a-xna -fps計數器/

有沒有辦法持續更新FPS標簽?

這是我剛才寫的FPS計數器課程。 您應該能夠將其放入代碼中並按原樣使用它。

public class FrameCounter
{
    public FrameCounter()
    {
    }

    public long TotalFrames { get; private set; }
    public float TotalSeconds { get; private set; }
    public float AverageFramesPerSecond { get; private set; }
    public float CurrentFramesPerSecond { get; private set; }

    public const int MAXIMUM_SAMPLES = 100;

    private Queue<float> _sampleBuffer = new Queue<float>();

    public override bool Update(float deltaTime)
    {
        CurrentFramesPerSecond = 1.0f / deltaTime;

        _sampleBuffer.Enqueue(CurrentFramesPerSecond);

        if (_sampleBuffer.Count > MAXIMUM_SAMPLES)
        {
            _sampleBuffer.Dequeue();
            AverageFramesPerSecond = _sampleBuffer.Average(i => i);
        } 
        else
        {
            AverageFramesPerSecond = CurrentFramesPerSecond;
        }

        TotalFrames++;
        TotalSeconds += deltaTime;
        return true;
    }
}

您需要做的就是在主Game類中創建一個成員變量。

    private FrameCounter _frameCounter = new FrameCounter();

並在Game的Draw方法中調用Update方法並繪制標簽,但是你喜歡..

    protected override void Draw(GameTime gameTime)
    {
         var deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

         _frameCounter.Update(deltaTime);

         var fps = string.Format("FPS: {0}", _frameCounter.AverageFramesPerSecond);

         _spriteBatch.DrawString(_spriteFont, fps, new Vector2(1, 1), Color.Black);

        // other draw code here
    }

請享用! :)

您可以使用以下公式在任何給定時刻獲取當前幀速率:

framerate = (1 / gameTime.ElapsedGameTime.TotalSeconds);

下面介紹的其他兩種方法都會為您提供修改后的幀速率,使其更平滑,並且返回值的波動更小

這個通過在對數刻度上對所有先前的幀時間進行加權來工作。 我不喜歡使用平均值來獲得游戲性能指標的想法,因為沒有很好地表示框架(或者如果你有很高的平均值),並且非常低/非常高的幀率具有非常不同的准確度,如果他們的平均運行率相同。

為了解決這個問題,我制作了一個SmartFramerate類(可怕的名字,我知道)

class SmartFramerate
{
    double currentFrametimes;
    double weight;
    int numerator;

    public double framerate
    {
        get
        {
            return (numerator / currentFrametimes);
        }
    }

    public SmartFramerate(int oldFrameWeight)
    {
        numerator = oldFrameWeight;
        weight = (double)oldFrameWeight / ((double)oldFrameWeight - 1d);
    }

    public void Update(double timeSinceLastFrame)
    {
        currentFrametimes = currentFrametimes / weight;
        currentFrametimes += timeSinceLastFrame;
    }
}

您在創建變量時設置權重:(較高的權重對於瞬時幀率更准確,較低的權重更平滑。我發現3-5是一個很好的平衡)

SmartFramerate smartFPS = new SmartFramerate(5);

在每幀運行的任何地方調用Update方法:

smartFPS.Update(gameTime.ElapsedGameTime.TotalSeconds);

可以像這樣訪問當前幀速率:

smartFPS.framerate

或印刷如下:

debuginfo.Update("\n\nᴥ" + smartFPS.framerate.ToString("0000"), true);

(我把它放到一個自定義的印刷類中,所以如果語法看起來很時髦,我會道歉)

但是,如果您希望簡單地將一定數量的幀平均在一起,那么這個類是我提出的最有效的方法。

class SmoothFramerate
{
    int samples;
    int currentFrame;
    double[] frametimes;
    double currentFrametimes;

    public double framerate
    {
        get
        {
            return (samples / currentFrametimes);
        }
    }

    public SmoothFramerate(int Samples)
    {
        samples = Samples;
        currentFrame = 0;
        frametimes = new double[samples];
    }

    public void Update(double timeSinceLastFrame)
    {
        currentFrame++;
        if (currentFrame >= frametimes.Length) { currentFrame = 0; }

        currentFrametimes -= frametimes[currentFrame];
        frametimes[currentFrame] = timeSinceLastFrame;
        currentFrametimes += frametimes[currentFrame];
    }
}

要使用它,只需初始化一個SmoothFramerate變量,只要你希望使用它,傳遞你想要平均的幀數:

SmoothFramerate smoothFPS = new SmoothFramerate(1000);

完全像使用上面的SmartFramerate類一樣更新,訪問和打印當前幀速率。

感謝閱讀,我希望這可以幫助別人。

使用double來測量fps:

double frameRate = 0.0;

修改方法Update如下:

public override void Update(GameTime gameTime)
{        
    if(gameTime.ElapsedGameTime.TotalSeconds > 0.0)
    {
        frameRate = (double)frameCounter / gameTime.ElapsedGameTime.TotalSeconds;
    }
    frameCounter = 0;
}

我沒有測試代碼,但你應該明白這個想法。

您可能嘗試在每次繪制操作中更新FPS。 這將是非常不穩定的價值,因為有時您需要更多,有時更少。 為了使價值更穩定 - 從許多價值中取平均值。

計算FPS的最簡單方法可能是計算圖紙。 而且具有定時器功能的每秒可以說這個值,計算新的fps和清除計數器。 使此計時器更長(例如2秒),或者只是取最后10個fps值並顯示平均值。

在一些游戲中,我看到他們也計算了重繪場景所需的最長時間。 這也可能是一個有趣的價值。 為此,您可以測量繪制函數需要多長時間:在開始時記錄時間,在結束時,差異將是時間。

請注意,如果啟用同步,則延遲繪制操作直到下次同步,這可能是奇怪結果的原因?

更新每個Draw()的簡單方法是:

frameRate = 1 / gameTime.ElapsedGameTime.TotalSeconds;

您也可以在Update()方法中刪除它,以查看觸發的頻率,如果您願意的話。

如果你想減慢更新的速度......

frameRate += (((1 / gameTime.ElapsedGameTime.TotalSeconds) - frameRate) * 0.1);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM