Jef*_*eff 10 c# xna frame-rate monogame
我试图获得我游戏的当前FPS,但是我只能找到每秒更新FPS变量的方法.例如https://github.com/CartBlanche/MonoGame-Samples/blob/master/Draw2D/FPSCounterComponent.cs和http://www.david-amador.com/2009/11/how-to-do-a-xna -fps计数器/
有没有办法持续更新FPS标签?
cra*_*mes 26
这是我刚才写的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;
}
}
Run Code Online (Sandbox Code Playgroud)
您需要做的就是在主Game类中创建一个成员变量.
private FrameCounter _frameCounter = new FrameCounter();
Run Code Online (Sandbox Code Playgroud)
并在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
}
Run Code Online (Sandbox Code Playgroud)
请享用!:)
您可以使用以下公式在任何给定时刻获取当前帧速率:
framerate = (1 / gameTime.ElapsedGameTime.TotalSeconds);
Run Code Online (Sandbox Code Playgroud)
下面介绍的其他两种方法都可以为您提供经过修改的帧速率,旨在使帧速率更平滑并且返回值的波动较小
这是通过以对数比例对所有先前帧时间加权来实现的。我不喜欢使用平均值来获得游戏性能指标的想法,因为不能很好地表示丢帧(或者如果您有很高的平均值,则根本不表示),并且如果帧率非常低/非常高,则帧间的准确性差异很大它们以相同的平均值运行。
为了解决这个问题,我制作了一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
在创建变量时设置权重:(权重越高,瞬时帧速率越准确,权重越低,平滑度越高。我发现3-5是一个很好的平衡点)
SmartFramerate smartFPS = new SmartFramerate(5);
Run Code Online (Sandbox Code Playgroud)
在将每帧运行的任何地方调用Update方法:
smartFPS.Update(gameTime.ElapsedGameTime.TotalSeconds);
Run Code Online (Sandbox Code Playgroud)
可以像这样访问当前帧速率:
smartFPS.framerate
Run Code Online (Sandbox Code Playgroud)
或像这样打印:
debuginfo.Update("\n\n?" + smartFPS.framerate.ToString("0000"), true);
Run Code Online (Sandbox Code Playgroud)
(我将其放入自定义打印类中,因此,如果语法看起来很时髦,我深表歉意)
但是,如果您只想将一定数量的帧平均在一起,那么该类是我想出的最有效的方法。
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];
}
}
Run Code Online (Sandbox Code Playgroud)
要使用它,只需在要使用它的地方初始化一个SmoothFramerate变量,并传递要平均的帧数:
SmoothFramerate smoothFPS = new SmoothFramerate(1000);
Run Code Online (Sandbox Code Playgroud)
完全像使用上面的SmartFramerate类一样更新,访问和打印当前帧速率。
感谢您的阅读,希望对您有所帮助。