我刚开始使用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游戏,手绘动画。答案 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.Count
和isLooping
位,但应该很容易将这些位添加回去。您可能还想将timeUntilNextFrame
初始化为animationFrameTime
对于第一帧。
只需用这段代码警告一句话,如果游戏由于某种原因而运行缓慢(或者可能暂停了)gameFrameTime
可能会导致一些非常大的值导致一些奇怪的行为。我不完全确定MonoGame / XNA是否会发生这种情况,但至少值得考虑。
答案 1 :(得分:0)
事实证明这是一个众所周知的问题。基本上它的数学上不可能在30个游戏fps中捕获24个动画fps,因为它们并不是彼此独立的。插值是解决此问题的唯一方法。每当你在一台60赫兹的显示器上观看24 fps电影时,这就完成了。