SFML community forums

General => SFML wiki => Topic started by: Foaly on January 13, 2013, 04:03:26 pm

Title: Animated Sprite class
Post by: Foaly on January 13, 2013, 04:03:26 pm
Hello everybody!
I wrote a class that provides an easy interface to Animations and follows the design of sf::Spite. I find it very helpful, so I though I share it with everybody! Go check it out and tell me what you think! Any input is appreciated.
Here is the link to the Wiki page (https://github.com/SFML/SFML/wiki/Source%3A-AnimatedSprite).
Title: Re: Animated Sprite class
Post by: eXpl0it3r on January 13, 2013, 04:20:33 pm
Seems quite nice, though not as flexible as Thor's animation class, but for a simple animation it's straight forward. :)

Wouldn't it make more sense to call the function addFrame instead of pushBackFrame or if you want to go with push back, then why not simply push_back?

Could please include a proper license? Because
You can use it in any way you want. Just a little note that the class was written by me would be nice :)
doesn't legally hold up. It also doesn't exactly specify, if the mentioning is required or just wished.
If you don't specify any license it will automatically fall into the public domain as stated by the wiki rules. ;)
Title: Re: Animated Sprite class
Post by: Foaly on January 13, 2013, 05:35:22 pm
Of course if you already use thor, than this will not be a replacement, because thor offers stuff like fading etc. But if you only need frame-based animation and don't want to include a big library than this class might be the way to go. Plus I designed my class to have a simple interface similar to sf::Sprite, so it's perfect for beginners. There where a bunch of different source codes on the old wiki on how to do animations (all using 1.6), but there is non on the new wiki using SFML 2.0 (with a clean interface).

I renamed pushBackFrame to addFrame, because it makes a lot more sense :D Thanks for the tip.

I'll think about what license to use. Probably zlib/png, but I'm not quiet sure yet.

I would love to see if somebody took a look at the code and checked if I got all the const's correct and if I don't do unnecessary copies. I tried, but I'm not sure if I got everything right. I know there are people here who love that stuff ;)
Title: Re: Animated Sprite class
Post by: Foaly on January 13, 2013, 06:09:54 pm
Hmm I just noticed something weird...
If I rotate (both rotate() or setRotation()) the AnimatedSprite by 45 or -45 degrees the texture coordinates are not calculated correctly. The first and third frame (same one) are calculated correctly, but the second frame is offset one to the left and the fourth is offset on to the right. This only happens with 45 or multiples of it (405,...) and -45 or multiples of it.

Does anybody have an idea, why this could happen? The sf::Transform should not affect the texture coordinates, should it? It only affects the vertices, right?

edit: I just noticed that sf::Sprite has the same problem.
Title: Re: Animated Sprite class
Post by: Nexus on January 14, 2013, 08:34:49 pm
The class looks primarily good, I like that you use RAII and don't inherit from sf::Sprite ;)
Still some advice, as requested:

Make your code const-correct. Top-level CV qualifiers for parameters like const std::size_t n are useless, as explained here (http://en.sfml-dev.org/forums/index.php?topic=2767.msg18197#msg18197).
std::size_t getSize();
// -->
std::size_t getSize() const;

sf::IntRect& getFrame(const std::size_t n);
// ->
sf::IntRect getFrame(std::size_t n) const; // or
const sf::IntRect& getFrame(std::size_t n) const;
And if the animation isn't modified in the animated sprite, you can make the pointers and references to it const, too.

AnimatedSprite's constructor should be explicit, and you should initialize everything in its initializer list. Also, it's not exactly clear in which cases you cast int to float... Basically, there exists an implicit conversion, but to make it expressive in the code, you can (but don't have to) use static_cast.
Title: Re: Animated Sprite class
Post by: Foaly on January 16, 2013, 10:07:01 am
First of all thank you very much for the post! I knew I would miss something :D I made the functions you named const correct  (include the animation in animated sprite, since it's not modified) and initialized everything in the initializer list. I also added the setFrame() function, that allows you to jump to a certain frame in the animation, which solves a bug, I noticed (when you first set the animation, the frame isn't set right away... anyway that's fixed).
I know there is an implicit conversion for variables. I took those parts from sf::Sprite's class. I guess it's more noticeable that a conversion is taking place this way.
I don't quiet understand why AnimatedSprite's constructor should be explicit though. Could you explain this to me?
Thanks again for the helpful post :)

edit: i also added a proper license (zlib/libpng)
Title: Re: Animated Sprite class
Post by: Nexus on January 16, 2013, 10:17:24 am
The constructor is currently declared as follows. It can be called with 0, 1, 2, or 3 arguments.
AnimatedSprite(sf::Time frameTime = sf::seconds(0.2), bool paused = false, bool looped = true);

Every constructor that can be invoked with 1 argument provides an implicit conversion of the argument to the object. In your example, the following code works:
sf::Time time = sf::seconds(5);
AnimatedSprite sprite = time;

This is certainly not intended, and a potential source of errors. By using the explicit keyword, you make the conversion explicit. The above code won't compile anymore, instead you have to use the constructor syntax:
sf::Time time = sf::seconds(5);
AnimatedSprite sprite(time);
Title: Re: Animated Sprite class
Post by: Foaly on January 16, 2013, 10:23:38 am
Totally makes sense! I'll add it. Thanks for the explanation
Title: Re: Animated Sprite class
Post by: netrick on January 22, 2013, 09:22:43 pm
Very good work. It is great and extremely easy to use and is enough for most cases.
Title: Re: Animated Sprite class
Post by: Foaly on January 22, 2013, 09:37:34 pm
Well thank you very much! I'm glad to hear that my class is useful to somebody!
I'd love to hear about every project that uses my class.
And of course if you find something to improve let me know! (because the real bugs usually show up, when the code is used extensively) :)
Title: Re: Animated Sprite class
Post by: Foaly on August 31, 2013, 05:44:03 pm
Hello everybody!
Like I said, the real bugs only show up, if the class is in use for some time.
I had some time today and looked at the code again and noticed a few errors.
I updated the code on the wiki to fix these errors. Here is a list of what changed:
I recommend everybody that uses the class to update their code, especially because of the last two changes.
If somebody finds another error or has some other improvement, feel free to post a message!
Have fun animating! :)
Title: Re: Animated Sprite class
Post by: prchakal on September 11, 2013, 07:04:18 pm

Only left a link to download it inside a ZIP with the version, like: AnimatedSpriteClass-012.zip.

Title: Re: Animated Sprite class
Post by: makerimages on December 01, 2013, 12:37:23 pm
using this for some experimenting, seems simple and easy enough to grab a hold of in a few minutes. What would be nice though, is to be able to set the frame to one fixed frame and then be able to for example only animate frames 2-6 and return pack to frame 1 when done, or something like that.
Title: Re: Animated Sprite class
Post by: Foaly on December 01, 2013, 07:33:04 pm
I don't really understand what you mean.
The AnimatedSprite class always uses fram 0 as the "fixed/default frame", that it returns to after the animation is done and not looped. If you only want to play a subset of an Animation, simply split it up in two Animations. If you meant neither of those thing, please explain what you mean more clearly.
Title: Re: Animated Sprite class
Post by: DemonRax on December 27, 2013, 08:54:37 pm
Hey Foaly.

Thanks for the class! Helped me a lot as a beginner :)

There's a mystype if AnimatedSprite.cpp here, should be with newFrame,:
void AnimatedSprite::setFrame(std::size_t newFrame, bool resetTime)
sf::IntRect rect = m_animation->getFrame(newFrame);

I also attached modified version with backwards loop added and the formentioned piece fixed, if you're interested. And I also changed it so it stops at the last frame, because I thought this is correct way. Don't know for sure though.
Title: Re: Animated Sprite class
Post by: Foaly on December 30, 2013, 12:41:46 pm
Indeed! Nice bug! Thanks for pointing it out. That what happens, when you refractor with copy & paste... I fixed it on the wiki.
As for your example code. I will look at it when I find some time. (I wanted to write a better example since a long time, maybe I'll have some time over the break...)
edit: I had a quick look at your code and this is not how the class is supposed to be used(/extended). I'll try to write a better example soon.
About "stop()" I implemented it just like your CD/MP3 player would: play plays the animation, pause halts/pauses it and stop pauses it and resets it to the beginning. I find it logically that way, but of course you can modify the source in any way that fits your need ;)
Title: Re: Animated Sprite class
Post by: DemonRax on January 01, 2014, 05:08:50 pm
Yeah, I'm not saying you should use my example :) That's just the modified version I made for myself. But I thought the bug is quite important.

Funny thing is - it works same way, because it uses m_currentFrame variable when calling  the function and then basically the value is there, so you don't really need internal newFrame :) But when I tried to setFrame manually it made me scratch my head for a while before I've noticed the mistype.

Looking forward for the extended class! Thanks!
Title: Re: Animated Sprite class
Post by: Foaly on January 02, 2014, 11:00:36 pm
Luckily I found some time to write up a better example of how to use this class. I fixed yet another bug and uploaded a completly new example. Everybody please take a look at it and tell me what you think. I am open for comments and improvements!

check it out : https://github.com/SFML/SFML/wiki/Source:-AnimatedSprite
Title: Re: Animated Sprite class
Post by: damnednforsaken on March 26, 2014, 06:23:51 pm
A big class that I don't have to write myself score!
Seriously thank you for writing this tutorial.

Hmm I can't get to seem to get it to work though.

From the wiki I copied pasted, the individual files and made them into files. main,animations,animated sprites

When I run through g++ I get it to compile
g++ -c main.cpp ...........GOOD
g++ main.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system .........FAIL
So the linking fails,

g++ main.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system
main.o: In function `main':
main.cpp:(.text+0x254): undefined reference to `Animation::Animation()'
main.cpp:(.text+0x26d): undefined reference to `Animation::setSpriteSheet(sf::Textur\
e const&)'
main.cpp:(.text+0x2b1): undefined reference to `Animation::addFrame(sf::Rect<int>)'
main.cpp:(.text+0x2f5): undefined reference to `Animation::addFrame(sf::Rect<int>)'
main.cpp:(.text+0x339): undefined reference to `Animation::addFrame(sf::Rect<int>)'
main.cpp:(.text+0x37d): undefined reference to `Animation::addFrame(sf::Rect<int>)'
main.cpp:(.text+0x38c): undefined reference to `Animation::Animation()'
main.cpp:(.text+0x3a5): undefined reference to `Animation::setSpriteSheet(sf::Textur\
e const&)'
main.cpp:(.text+0x3e9): undefined reference to `Animation::addFrame(sf::Rect<int>)'
main.cpp:(.text+0x42d): undefined reference to `Animation::addFrame(sf::Rect<int>)'
main.cpp:(.text+0x471): undefined reference to `Animation::addFrame(sf::Rect<int>)'
main.cpp:(.text+0x4b5): undefined reference to `Animation::addFrame(sf::Rect<int>)'
main.cpp:(.text+0x4c4): undefined reference to `Animation::Animation()'
main.cpp:(.text+0x4dd): undefined reference to `Animation::setSpriteSheet(sf::Textur\

Not sure why, thoughts?
Title: Re: Animated Sprite class
Post by: damnednforsaken on March 26, 2014, 08:45:26 pm
Ughh... yea, Im dumb..
This was caused by not linking properly. KNOW your compiler/linker!!

Ok, I wasn't compiling all the files for ones so,
instead of
g++-c main.cpp
needed to do
g++ -c main.cpp Animation.cpp AnimatedSprite.cpp

and during the linker stage needed to do,
g++ AnimatedSprite.o Animation.o main.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system

ughh sorry bout all that.
Title: Re: Animated Sprite class
Post by: ImmutableMeta on February 07, 2015, 01:25:16 am
So, I have quite a few improvements to suggest, as well as some minor organizational changes I would make. But I think I will just write my own and post it :)
Title: Re: Animated Sprite class
Post by: Foaly on March 08, 2015, 01:52:12 pm
Please go ahead and tell us what you would change/improve. New stuff is always welcome!