My 2D animations are running much faster on high framerate compared to 60 FPS, even worse at 30 FPS.
I am using 2D animation class based on this blog post: http://rbwhitaker.wikidot.com/monogame-texture-atlases-2
The responsible code for setting the frames of my animations is the following:
Letâs say I have an animation that is running at 24 FPS, meaning that the value of the âdelayâ is 41.6 ms. When my game is running on very high (unlimited) FPS mode, the âelapsedTimeâ in very very small, meaning that the animation will change to the next frame accurately roughly at 41 ms.
But when my game is running 60 FPS (30 FPS is even worse), the increments of the âcurrentDelayâ will equal the elapsedTime, which is at first 16 ms, then 32, then 49ms, and thatâs when the animation will change frames, resulting in much slower animations on 60 FPS compared to uncapped gameplay.
Is there any trick to do this better? I would not like to cap my game to 60 FPS, but the difference is very visible and it fail to see how to improve this code and avoid this.
Iâd say moving your delay counter before you increment the animation frame may be part of the problem. Every animation frame will lag by one update frame with your current setup, and at lower FPS will be more noticeable.
I just reread your initial post⊠The change I cited in my previous post is probably not gonna change a whole lot, although I would recommend still doing it.
However, I do have a suggestion:
currentDelay += gameTime.ElapsedGameTime.TotalMilliseconds;
if (currentDelay >= delay)
{
CurrentFrame++;
currentDelay -= delay; //save remainder
//just in case of a lag spike, but may not be necessary
if (currentDelay >= delay)
{
currentDelay = 0;
}
}
This will save the leftover time in your currentDelay, so regardless of your frame pacing, your animation should still run at the same speed.
The way I do my animations is that I have a float variable m_frameTime on each game object and I set it to the amount of time I want before it moves to the next frame. I subtract out the GameTime.Elapsed on each Update loop and when m_frameTime <= 0 then I move to the next frame. So my animation speed is dependent upon time and not the number of frames.
You will skip to the next animation when m_frametime < 0. But there will be some left over frame. That leftover frametime will change depending on fps and the time for each frame jump.
Unless you add the leftover animation into the next m_frametime
m_frametime = 4
If on each frame at a constant fps (for simplicityâs sake) your taking m_frametime - 0.6f.
On the 6th frame, frame time would be down to 0.4f (7 * 0.6f) still more than zero)
On the 7th frame it would equal -0.2f. Which is less than zero. Now if you reset your m_frametime back to 4. On a fixed fps you wouldnât notice as your getting a new animation every 7 frames.
On a variable fps, because your not using the remainder -0.2f, your frametime will not update consistently.
On a high fps it wonât be noticeable. On a low fps you will get a jitter every now and then.
The way to fix that would be to use that remainder 0.2f and add it back (edit: subtract it from) on the m_frametime. So the next m_frametime will be 4.2f (edit 3.8f)
Just quickly read your answer. So not sure, but wouldnât you need to subtract it from m_frametime? Since you want to account for the already passed time?
Thanks, Iâll check this! I was looking at your engine, and man, I have to say our way of thinking is just ridiculously similar! The engine youâre working is very similar to mine, they way youâre handling your layers, your animations (apart from my bug), having actions when your animation ends, etc. even our naming is very similar.
Keep up the good work!
So the problem is that youâre doing very discrete operations on continuous data.
You have a few options with different considerations.
Maintain the âadvance frame when boundary crossedâ approach and try and finagle exact times. Youâve got some good options already in the thread for this.
Use modulus arithmetic. Works IFF all frames are the same length, and the number of milliseconds isnât well, at least until the TotalMillisecondsâ mantissa loses ones digit precision, after the gameâs been running for 70 thousand years.