I've been trying to animate an sf::Sprite with Thor 2.1, but as of now my sprite only displays one frame of each animation, not going through all of them.
I've got a sample spritesheet out of one of SFML's tutorials for spritesheets:
My code (schematic code, not the whole):
#include<SFML/Window.hpp>
#include<SFML/Audio.hpp>
#include<SFML/Graphics.hpp>
#include<SFML/System.hpp>
#include<SFML/Main.hpp>
#include<stdlib.h>
#include<iostream>
#include <Thor/Animations.hpp>
int main()
{
sf::Texture texPlayer;
texPlayer.create(96, 128);
if (!texPlayer.loadFromFile(workingDirectory + "\\textures\\animtest.png"))
{
std::cout << "can't load" << std::endl;
}
sf::Sprite sprPlayer;
sprPlayer.setTexture(texPlayer);
thor::FrameAnimation playerDown;
playerDown.addFrame(10.0f, sf::IntRect(0 , 0, 32, 32));
playerDown.addFrame(10.0f, sf::IntRect(32, 0, 32, 32));
playerDown.addFrame(10.0f, sf::IntRect(64, 0, 32, 32));
thor::FrameAnimation playerLeft;
playerLeft.addFrame(20.0f, sf::IntRect(0 , 32, 32, 32));
playerLeft.addFrame(20.0f, sf::IntRect(32, 32, 32, 32));
playerLeft.addFrame(20.0f, sf::IntRect(64, 32, 32, 32));
thor::FrameAnimation playerRight;
playerRight.addFrame(30.0f, sf::IntRect(0 , 64, 32, 32));
playerRight.addFrame(30.0f, sf::IntRect(32, 64, 32, 32));
playerRight.addFrame(30.0f, sf::IntRect(64, 64, 32, 32));
thor::FrameAnimation playerUp;
playerUp.addFrame(40.0f, sf::IntRect(0 , 96, 32, 32));
playerUp.addFrame(40.0f, sf::IntRect(32, 96, 32, 32));
playerUp.addFrame(40.0f, sf::IntRect(64, 96, 32, 32));
thor::AnimationMap<sf::Sprite, std::string> playerAMap;
playerAMap.addAnimation("down" , playerDown , sf::seconds(2.0f));
playerAMap.addAnimation("left" , playerLeft , sf::seconds(3.0f));
playerAMap.addAnimation("right", playerRight, sf::seconds(4.0f));
playerAMap.addAnimation("up" , playerUp , sf::seconds(5.0f));
thor::Animator<sf::Sprite, std::string> playerAnimator = thor::Animator<sf::Sprite,
std::string>::Animator(playerAMap);
sf::Clock animFrameTime;
sf::RenderWindow window;
window.create(sf::VideoMode(800, 450), "Placeholder", sf::Style::Default);
while (window.isOpen())
{
// here's movement direction checking, event handling, dealing with movement overall
// let's say we dont use any of that now and we want to play just the "up" animation
playerAnimator.play() << "up" << thor::Playback::loop("up");
playerAnimator.update(animFrameTime.restart());
playerAnimator.animate(sprPlayer);
window.draw(sprPlayer);
}
return 0;
}
As I said, the behaviour of that code is it just plays the first frame of up animation (in this case the upper-left frame of the spritesheet).
For "left" animation it plays the first frame of the second row, and for all the others respectively.
First,
texPlayer.create(96, 128);
is not needed, as you immediately load a file and thus overwrite the texture. sf::Texture::create()
is mainly useful when you edit the texture after loading it, or use it for low-level OpenGL.
The thor::Animator
can be understood to have two modes of operation, each of which covers a few methods:
play()
, stop()
, queue()
update()
, animate()
update()
in a fixed-time logic step.Those are already all the methods that thor::Animator
offers, see official documentation.
The mistake in your code is that you call play()
in every frame, thus restarting the animation constantly. What you should do instead is call play()
before the while
loop. Since you specified thor::Playback::loop()
, the animation will be looping as long as you update the animator.