# Time Required for Animation to Finish

Using a tutorial found on the AppHub, I've been attempted to add controls to a sample sprite sheet. I am able to get all the animations working, but for stuff like punching or stabbing, the animations require a timer to stop them from playing repeatedly. XNA uses a default framerate of 60, but I have the animations running at 10 FPS using the following code:

int punchIndex = walk.GetIndex("obj_Walk000");

punchIndex += (int)(time * animationFPS) % punchFC;
batch.Draw(punch.Texture, position, punch.SourceRectangle(punchIndex), Color.White, rotation, origin, 1.0f, SpriteEffects.FlipHorizontally, 1.0f);
break;


Where animationFPS = 10 and punchFC is 6, which is the number of frames in the animation. Using this data, I have calculated a required time of 0.5 seconds for the animation to complete, but that seems to be incorrect, so I'm looking for someone to show me how to do the math properly.

• I don't think XNA uses a fixed FPS. I thought it uses a variable FPS that depends on your CPU and stuff. – ashes999 Mar 5 '12 at 4:31
• @ashes999 There's a property to toggle between fixed time step and variable time step in XNA. When running in fixed time step, if performance starts suffering and it can't keep up with the specified time step, you're warned through another property. – David Gouveia Mar 5 '12 at 4:34

First of all I recommend separating it so that the frame is updated in the Update method instead of the Draw method. That's because XNA is free to skip a few Draw calls to make up for lost time when the game runs slowly, but not Update, so it should run more consistently.

It's also a better idea to leave the Draw method just for rendering, and putting any state changes in the Update method of your classes.

Now for your problem, here's the basic structure of how to enforce an animation framerate indepdentent of the game's framerate (in this example 10 FPS):

private float _timer = 0.0f;
private float _framerate = 10f;
private int _currentFrame = 0;
private int _frameCount = 6;
private bool _animating = true;

public void Update(GameTime gameTime)
{
if(!_animating) return;

_timer += (float)gameTime.ElapsedGameTime.TotalSeconds;

if (_timer >= 1.0f / _framerate)
{
_timer -= 1.0f / _framerate;
_currentFrame = (_currentFrame + 1) % _frameCount;

if(_currentFrame == 0)
{
_animating = false;
_timer = 0f;
}
}
}

public void Draw(GameTime gameTime)
{
// Draw _currentFrame
}


Of course you can precalculate and store 1.0f / _framerate to avoid having to recompute it every frame.

• Enforcing the framerate has not been the issue. I'm trying to stop an animation after all of its frames have been drawn once. That is good to know that XNA can skip Draw calls though - I will move that logic. – 131nary Mar 5 '12 at 4:46
• @131nary Okay I edited it once more and consolidated all the checks in the same example this time. – David Gouveia Mar 5 '12 at 4:54
• Ah ok. Instead of having a set time, you simply check if you've cycled through. That's a more elegant solution. – 131nary Mar 5 '12 at 4:56
• @131nary Exactly, and simpler too. Of course there's room for variation. You might for instance prefer to stop the animation at the final frame instead of waiting for it to loop back to the start, but you get the idea. Either way, it's easier to just handle this when the frame changes, instead of messing with time. – David Gouveia Mar 5 '12 at 4:59