动画帧率与游戏fps

时间:2017-01-02 22:06:38

标签: c# monogame

我刚开始使用MonoGame时是初学程序员。我正在实现一些运行动画的代码,并遇到了一个我不知道如何解决的问题。这是我在AnimationManager类中使用的代码:

public void Update(GameTime gameTime)
{
    timeElapsed += (float)gameTime.ElapsedGameTime.TotalSeconds;

    if (timeElapsed > timeToUpdate)
    {
        timeElapsed -= timeToUpdate;
        //Tried to just reset timeElapsed to zero, still doesn't work
        //timeElapsed = 0;
        if (frameIndex < rectangles.Count -1)
        {
            frameIndex++;
        }
        else if (isLooping)
        {
            frameIndex = 0;
        }
    }
}

问题是我以每秒24帧的速度制作动画,当游戏以60或30 fps的速度运行时,在每次更新代码检查时,是时候绘制一个新的动画帧,你得到一些剩余的帧,因为你试过每秒平均绘制24幅图像,每秒30个游戏帧。所以剩下6帧。结果是大约6帧的动画被绘制两次,一些被跳过,整个动画大约长25%。有没有办法来解决这个问题?我是否可以将此代码移动到Draw调用,然后以48 fps为60 fps游戏限制绘制调用,因此每个动画帧将在每次绘制调用时绘制。如果这是一个合理的解决方案,我不知道如何做到这一点?

VSync最终会如何影响所有这些。它会搞乱动画帧,即使这个问题已经解决了。

编辑:忘了说这是一部2D游戏,手绘动画。

2 个答案:

答案 0 :(得分:1)

通常,当您执行此类操作时,您不必担心VSync或您的游戏以60或30 fps运行。这几乎无关紧要。

重要的是,您知道动画每秒所需的帧数以及单个游戏帧需要多长时间。

由此可以计算单个动画帧中的时间长度。例如,您最终得到的结果如下:

var animationFrameTime = 1f / 24f;   // 24 frames per second

到目前为止一切顺利。

接下来你需要做的是开始在某个地方积累时间。有几种不同的方式来思考这个问题。我喜欢用直到下一帧剩下多少时间来考虑它。

var gameFrameTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
timeUntilNextFrame -= gameFrameTime;

然后,当您用完帧时间时,您需要增加frameIndex

if(timeUntilNextFrame <= 0)
{
    frameIndex++;
    timeUntilNextFrame += animationFrameTime;
}

注意这里的重要一点。我已animationFrameTime 添加到timeUntilNextFrame。这样,如果从前一帧开始有任何剩余时间,它将被添加到下一帧,保持动画流畅。

真的没有那么多。我已经遗漏了rectangles.CountisLooping位,但应该很容易将这些位添加回去。您可能还想将timeUntilNextFrame初始化为animationFrameTime对于第一帧。

只需用这段代码警告一句话,如果游戏由于某种原因而运行缓慢(或者可能暂停了)gameFrameTime可能会导致一些非常大的值导致一些奇怪的行为。我不完全确定MonoGame / XNA是否会发生这种情况,但至少值得考虑。

答案 1 :(得分:0)

事实证明这是一个众所周知的问题。基本上它的数学上不可能在30个游戏fps中捕获24个动画fps,因为它们并不是彼此独立的。插值是解决此问题的唯一方法。每当你在一台60赫兹的显示器上观看24 fps电影时,这就完成了。

https://en.wikipedia.org/wiki/Three-two_pull_down