Okay here is some code out the SFML Game Development book, it shows animating a spritesheet. I'll go over what it is doing step by step.
P.S. Ignore the bad formatting ;p. Visual Studio's formatting does not play nicely with github sometimes.
https://gist.github.com/bjumbeck/5d695bfb62313fab33d5
Now this is a wrapper class to make an animated sprite, the main functionality is inside of the update() method so lets go over that.
1 2
|
sf::Time timePerFrame = duration / static_cast<float>(numFrames);
elapsedTime += dt;
|
The first line what we are doing is getting the amount of time we want each frame of our animation to play. We do this by taking the duration (The total time we want the animation to play for) and dividing it by the number of frames are in that animation sequence.
Next we are adding the delta time to our elapsed time. The deltatime is how many seconds has passed since the last frame, by last frame I mean the last time our main game loop has ran, not our last animation frame. The elapsed time variable is used to track how much time has passed since we last ran any of the animation updating code (The stuff inside of the while loop below).
1 2
|
if (currentFrame == 0)
textureRect = sf::IntRect(0, 0, frameSize.x, frameSize.y);
|
This code should be obvious but just in case it is saying if our currentFrame variable is saying it is the first frame we will change our texture rectangle so that it is positioned on the first frame of the sprite sheet.
while (elapsedTime >= timePerFrame && (currentFrame <= numFrames || repeat))
Now this line of code is how we slow down our animation so to speak. Remember that elapsedTime is the total amount of time since we last ran our animation code (The code inside of this while loop) and timePerFrame is the the amount of time we want each frame to have.
So with that code we will only run our animation update code which will do the actual spirtesheet animation only when our elapsedTime variable is greater than or equal to timePerFrame.
The next part is to handle repeating the animation so it is looping and stopping the animation if it is not. This is pretty much what you wanted to know and will handle slowing down your animation. But I will go over the other parts briefly also.
1 2 3 4 5 6 7
|
textureRect.left += textureRect.width;
if (textureRect.left + textureRect.width > textureBounds.x)
{
textureRect.left = 0;
textureRect.top += textureRect.height;
}
|
Now you should be familiar with most of this code since it is just moving the texture rectangle around on the spritesheet so that different images are displayed.
The first line is basically just moving the texture rectangle one image to the right (Note this assumes that all sprites in the spritesheet are aligned in a row/column nature and have the same dimension).
The next set of code just handles moving the texture rectangle down a row if it is at the last column of the spritesheet.
elapsedTime -= timePerFrame;
Now this line is very important, remember in the beginning when I said that elapsedTime is what is in charge of keeping track of how much time has pasted since we last ran this while loop animation code? Well now that we are in the while loop and doing our animation code we need to reset that.
So what we do is minus the time it takes for one frame of our animation to run (Since we are updating our animation frame with this code).
1 2 3 4 5 6 7 8 9 10 11
|
if (repeat)
{
currentFrame = (currentFrame + 1) % numFrames;
if (currentFrame == 0)
textureRect = sf::IntRect(0, 0, frameSize.x, frameSize.y);
}
else
{
++currentFrame;
}
|
This bit of code is just handling animation repeating/looping. It is basically saying if we have checked the repeat flag it will run through the code need to repeat the animation if we are on the last frame of the animation. Otherwise if the repeat flag is false we just go to the next frame (Other code handles the animation ending if it is past the last frame).
sprite.setTextureRect(textureRect);
And finally outside of the while loop we run this code which will set the texture rectangle of the sprite which is a member of our class to the correct image in the spritesheet.
And that is about it, you don't have to put all this in a class like the SFML book did, but at least this should show you how your problem can be solved. The main part that you want to look at is these
1) Everything above the while loop
2) The while loop condition
3)
elapsedTime -= timePerFrame;
All those pertain to the problem you are facing.
Hopefully I did a decent job of explaining the code, been a bit since I have used SFML so am a bit rusty ;p. If you have any questions of don't understand anything from here just let me know.