【问题标题】:Animation frame rate vs game fps动画帧率与游戏 fps
【发布时间】:2017-09-04 07:50:01
【问题描述】:

我是一名刚开始接触 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 call,然后在 60 fps 游戏中将 draw call 限制在 48 fps,因此每个动画帧将在每第二个 draw call 时绘制。如果这是一个合理的解决方案,我不知道该怎么做?

VSync 最终将如何影响这一切。即使解决了这个问题,它会不会弄乱动画帧。

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

【问题讨论】:

  • 您可能应该考虑在动画帧之间进行一些插值(线性插值可能就足够了)。这样不同的帧率应该不会成为问题(仍然存在一些问题)
  • 不知道插值,总初学者.. :) 我现在正在阅读它。是否适用于二维?
  • 我不确定我是否理解您对每秒 24 帧与 30 帧的解释。动画可能应该在经过一段时间后交换精灵来绘制,这就是您的更新代码似乎正在做的事情。您的解释过于深入您认为问题可能是什么,而不是问题是什么。也许您可以改写问题并更笼统地解释实际和期望的行为是什么?
  • 插值可以应用于任何具有不同值的东西,无论是图像、动画 (2d/3d)、模型、数字……它的用途之一是计算 2 个不同值之间的值“步骤”(例如:平滑过渡)。下面的答案绝对是一个更简单的解决方案,但插值也允许使用一些更高级的技术(例如:在两个不同的动画之间创建平滑过渡) - 您需要评估您对特定情况的需求

标签: c# monogame


【解决方案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 中发生,但至少值得考虑。

【讨论】:

  • animationFrameTime 不应该是 animationFrameTime = 1f / 24f; ?
  • @MikeJohnson 很好地发现了。固定。
【解决方案2】:

原来这是一个众所周知的问题。基本上它在数学上不可能在 30 游戏 fps 中卡住 24 动画 fps,因为它们不是相互独立的。插值是解决此问题的唯一方法。每当您在 60 赫兹的显示器上观看 24 fps 的电影时,所做的事情都是一样的。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多