This class is very simple. It assumes you keep your animated sprites in a simple format.
Each sprite image must be identical in size, and arranged in a grid format. The frames are indexed from zero, and increase left to right and down the image.
For example this would be indexed like this
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
As each sprite is 47px by 64px You would use this AniSprite Sprite(Image,47,64);
Usage Example
sf::RenderWindow App(sf::VideoMode(1440, 900), "Test"); // Load a sprite to display sf::Image Image; if (!Image.LoadFromFile("characters.bmp")) return EXIT_FAILURE; AniSprite Sprite(Image,47,64); Sprite.SetLoopSpeed(60); //60 fps Sprite.Play(); while(App.IsOpened()) { // Clear screen App.Clear(); //update sprite antimation Sprite.Update(); App.Draw(Sprite); App.Display(); }
AniSprite.h
#pragma once #include <SFML/Graphics.hpp> class AniSprite : public sf::Sprite { public: AniSprite(); //initialtion list AniSprite(const sf::Image& Img, int frameWidth, int frameHeight); ~AniSprite(void); //Get sf::IntRect AniSprite::GetFramePosition(int frame); int GetFrameCount(); //set void SetFrameSize(int frameWidth, int frameHeight); //Sets current frame void SetFrame(int frame); //sets loop speed in fps void SetLoopSpeed(float fps); //start looping void Play(); void Play(int start, int end); //stop void Stop(); //draw functions void Update(); private: sf::Clock clock; float fps; bool isPlaying; int loopStart; int loopEnd; int currentFrame; int frameWidth; int frameHeight; };
AniSprite.cpp
#include "AniSprite.h" AniSprite::AniSprite(void) : sf::Sprite() { this->fps=1; this->currentFrame=0; this->isPlaying = false; this->loopStart = 0; this->SetFrameSize(0, 0); } AniSprite::AniSprite(const sf::Image& Img, int frameW, int frameH) : sf::Sprite(Img) { this->fps=1; this->currentFrame=0; this->isPlaying = false; this->loopStart = 0; this->SetFrameSize(frameW, frameH); //now calculate stuff } AniSprite::~AniSprite(void) { } int AniSprite::GetFrameCount() { unsigned int across = this->GetImage()->GetWidth() / this->frameWidth; unsigned int down = this->GetImage()->GetHeight() / this->frameHeight; return across*down; } //first frame is frame ZERO sf::IntRect AniSprite::GetFramePosition(int frame) { //get number across and down unsigned int across = (this->GetImage()->GetWidth() / this->frameWidth); unsigned int down = (this->GetImage()->GetHeight() / this->frameHeight); int tileY = frame / across ; //get Y on grid int tileX = frame % across ; //get X on grid sf::IntRect result( tileX*this->frameWidth, tileY*this->frameHeight, tileX*this->frameWidth + this->frameWidth, tileY*this->frameHeight + this->frameHeight); // for SFML 2.0 comment out above lines and use this instead /* sf::IntRect result( tileX*this->frameWidth, tileY*this->frameHeight, this->frameWidth, this->frameHeight); */ //end return result; } // void AniSprite::SetFrameSize(int frameW, int frameH) { this->frameWidth = frameW; this->frameHeight = frameH; this->SetSubRect(sf::IntRect(0,0,frameW,frameH)); } //Sets current frame void AniSprite::SetFrame(int frame) { this->currentFrame = frame; } //sets loop speed in fps void AniSprite::SetLoopSpeed(float newfps) { this->fps = newfps; } //start looping void AniSprite::Play() { this->Play(0,GetFrameCount()); } void AniSprite::Play(int start, int end) { loopStart = start; loopEnd = end; currentFrame = start; isPlaying = true; clock.Reset(); } //stop void AniSprite::Stop() { isPlaying = false; } //update function void AniSprite::Update() { if(isPlaying) { int frameCount = loopEnd - loopStart; // for sfml 2.0 replace the above line with... // int frameCount = (loopEnd+1) - loopStart; float timePosition = (clock.GetElapsedTime() * fps); currentFrame = loopStart + (int)timePosition % frameCount; //printf("%f:%i\n",clock.GetElapsedTime(),currentFrame); this->SetSubRect(GetFramePosition(currentFrame)); } }