动画帧率 vs 游戏 fps
Animation frame rate vs game fps
我是刚开始使用 MonoGame 的初级程序员。我正在为 运行 动画实现一些代码,遇到了一个我不知道如何解决的问题。这是我在 AnimationManager class:
中使用的代码
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 帧/秒的速度运行时,每次更新代码检查是时候绘制新的动画帧时,您会得到一些剩余的帧,因为你试图每秒平均绘制 24 张图像,每秒平均绘制 30 个游戏帧。所以还有剩下的 6 帧。这样做的结果是大约 6 帧动画被绘制了两次,有些被跳过了,整个动画长了大约 25%。有没有办法来解决这个问题?我是否可以将此代码移动到 Draw call,然后将 60 fps 游戏的 draw calls 限制在 48 fps,这样每个动画帧将在每隔一个 draw call 绘制。如果这是一个合理的解决方案,我不知道该怎么做?
VSync 最终将如何影响这一切。即使解决了这个问题,它会不会弄乱动画帧。
编辑:忘了说这是一款 2d 游戏,手绘动画。
通常,当您进行此类操作时,无需担心 VSync 或您的游戏 运行s 为 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.Count
和 isLooping
位,但将它们重新添加应该很容易。您可能还想将 timeUntilNextFrame
初始化为 animationFrameTime
第一帧。
只是对这段代码发出警告,如果游戏由于某种原因 运行 运行缓慢(或者可能暂停),gameFrameTime
最终可能会有一个非常大的值,导致一些奇怪的行为。我不完全确定这是否会在 MonoGame / XNA 中发生,但至少值得考虑。
原来这是一个众所周知的问题。基本上,在 30 个游戏 fps 中阻塞 24 个动画 fps 在数学上是不可能的,因为它们不是彼此独立的。插值是解决此问题的唯一方法。这与在 60 赫兹显示器上观看 24 fps 电影时所做的相同。
我是刚开始使用 MonoGame 的初级程序员。我正在为 运行 动画实现一些代码,遇到了一个我不知道如何解决的问题。这是我在 AnimationManager class:
中使用的代码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 帧/秒的速度运行时,每次更新代码检查是时候绘制新的动画帧时,您会得到一些剩余的帧,因为你试图每秒平均绘制 24 张图像,每秒平均绘制 30 个游戏帧。所以还有剩下的 6 帧。这样做的结果是大约 6 帧动画被绘制了两次,有些被跳过了,整个动画长了大约 25%。有没有办法来解决这个问题?我是否可以将此代码移动到 Draw call,然后将 60 fps 游戏的 draw calls 限制在 48 fps,这样每个动画帧将在每隔一个 draw call 绘制。如果这是一个合理的解决方案,我不知道该怎么做?
VSync 最终将如何影响这一切。即使解决了这个问题,它会不会弄乱动画帧。
编辑:忘了说这是一款 2d 游戏,手绘动画。
通常,当您进行此类操作时,无需担心 VSync 或您的游戏 运行s 为 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.Count
和 isLooping
位,但将它们重新添加应该很容易。您可能还想将 timeUntilNextFrame
初始化为 animationFrameTime
第一帧。
只是对这段代码发出警告,如果游戏由于某种原因 运行 运行缓慢(或者可能暂停),gameFrameTime
最终可能会有一个非常大的值,导致一些奇怪的行为。我不完全确定这是否会在 MonoGame / XNA 中发生,但至少值得考虑。
原来这是一个众所周知的问题。基本上,在 30 个游戏 fps 中阻塞 24 个动画 fps 在数学上是不可能的,因为它们不是彼此独立的。插值是解决此问题的唯一方法。这与在 60 赫兹显示器上观看 24 fps 电影时所做的相同。