Hello,
So I'm trying to use thor and things aren't going as smoothly as I thought they would. At the moment I have an isometric sprite sheet and I'm just trying to watch it animate the walk directions with W A S D and the diagonals of the keys. It must have something to do with the "queue" because it seems like a "lag" to the next animation and sometimes it never gets called even. I might be doing something wrong, but a lot of the functions in the tutorial aren't there. Such as
animator.
playAnimation("walk");
animator.
stopAnimation();
animator.
isPlayingAnimation()#include <Thor/Animations.hpp>
#include <Thor/Input.hpp>
#include <SFML/Graphics.hpp>
const int Sprite_Width = 160;
const int Sprite_Height = 160;
// Adds a range of frames, assuming they are aligned as rectangles in the texture.
// animation: FrameAnimation to modify
// x: Column index of the texture rectangle
// [yFirst,yLast]: Bounds for row indices (if yLast < yFirst, add frames in reverse order)
// duration: Relative duration of current frame (1 by default)
void addFrames(thor::FrameAnimation& animation, int x, int yFirst, int yLast, float duration = 1.f) {
const int step = (yFirst < yLast) ? +1 : -1;
yLast += step; // so yLast is excluded in the range
for (int y = yFirst; y != yLast; y += step)
animation.addFrame(duration, sf::IntRect(Sprite_Width * x, 160 * y, Sprite_Width, 160));
}
// Plays an animation, and updates the text correspondingly
// animator: Thor animator to play the animation
// animationId: Name of the animation to play
// restart: true if the queued animations are discarded, false if the new animation is enqueued at the end
// display: SFML text that displays the current animation
void playAnimation(thor::Animator<sf::Sprite, std::string>& animator, const std::string& animationId, bool restart, sf::Text& display) {
// Function to call before animation is played
auto onStart = [&display, animationId]() {
display.setString(animationId);
};
restart = false;
// Function to call after animation is played
auto onFinish = [&display]() {
display.setString("(idle)");
};
// Enqueue animation and callbacks -- restart determines whether queue is reset
(restart ? animator.play() : animator.queue())
<< thor::Playback::notify(onStart)
<< animationId
<< thor::Playback::notify(onFinish);
}
int main() {
sf::RenderWindow window(sf::VideoMode(1280, 768), "Thor Animation");
window.setVerticalSyncEnabled(true);
window.setKeyRepeatEnabled(false);
sf::Font font;
if (!font.loadFromFile("Media/sansation.ttf"))
return 1;
sf::Text animationText("(idle)", font, 14u);
animationText.setPosition(100.f, 150.f);
animationText.setFillColor(sf::Color(250, 215, 11));
// Create texture based on sf::Image
sf::Texture texture;
if (!texture.loadFromFile("Media/Sprite_1.png"))
return 1;
// Create sprite which is animated
sf::Sprite sprite(texture);
sprite.setPosition(100.f, 100.f);
// Define walk animation
thor::FrameAnimation walkDown;
for(auto i = 0; i < 8; i++)
addFrames(walkDown, i, 0, 0);
thor::FrameAnimation walkLeft;
for (auto i = 8; i < 16; i++)
addFrames(walkLeft, i, 0, 0);
thor::FrameAnimation walkRight;
for (auto i = 16; i < 24; i++)
addFrames(walkRight, i, 0, 0);
thor::FrameAnimation walkUp;
for (auto i = 0; i < 8; i++)
addFrames(walkUp, i, 1,1 );
thor::FrameAnimation walkDownLeft;
for (auto i = 8; i < 16; i++)
addFrames(walkDownLeft, i, 1, 1);
thor::FrameAnimation walkUpLeft;
for (auto i = 16; i < 24; i++)
addFrames(walkUpLeft, i, 1, 1);
thor::FrameAnimation walkDownRight;
for (auto i = 0; i < 8; i++)
addFrames(walkDownRight, i, 2, 2);
thor::FrameAnimation walkUpRight;
for (auto i = 8; i < 16; i++)
addFrames(walkUpRight, i, 2, 2);
// Register animations with their corresponding durations
thor::AnimationMap<sf::Sprite, std::string> animations;
animations.addAnimation("walkDown", walkDown, sf::seconds(1.f));
animations.addAnimation("walkLeft", walkLeft, sf::seconds(1.f));
animations.addAnimation("walkUp", walkUp, sf::seconds(1.f));
animations.addAnimation("walkRight", walkRight, sf::seconds(1.f));
animations.addAnimation("walkDownLeft", walkDownLeft, sf::seconds(1.f));
animations.addAnimation("walkUpLeft", walkUpLeft, sf::seconds(1.f));
animations.addAnimation("walkDownRight", walkDownRight, sf::seconds(1.f));
animations.addAnimation("walkUpRight", walkUpRight, sf::seconds(1.f));
// Create animator referring to this map, and play 'stand' animation to bring the sprite into an initial state
thor::Animator<sf::Sprite, std::string> animator(animations);
animator.play() << "walkDownLeft";
// Create clock to measure frame time
sf::Clock frameClock;
thor::ActionMap<std::string> keyMap;
thor::Action w(sf::Keyboard::W, thor::Action::Hold);
thor::Action a(sf::Keyboard::A, thor::Action::Hold);
thor::Action s(sf::Keyboard::S, thor::Action::Hold);
thor::Action d(sf::Keyboard::D, thor::Action::Hold);
keyMap["Down"] = s;
keyMap["Up"] = w;
keyMap["Left"] = a;
keyMap["Right"] = d;
thor::Action sa = s && a;
thor::Action wa = w && a;
thor::Action sd = s && d;
thor::Action wd = w && d;
keyMap["DownLeft"] = sa;
keyMap["UpLeft"] = wa;
keyMap["DownRight"] = sd;
keyMap["UpRight"] = wd;
thor::Action esc(sf::Keyboard::Escape, thor::Action::PressOnce);
thor::Action stop(sf::Keyboard::Space, thor::Action::PressOnce);
keyMap["quit"] = esc;
keyMap["Stop"] = stop;
// Main loop
while (window.isOpen()) {
// Handle events
sf::Event event;
while (window.pollEvent(event)) {
// React to different action types
if (keyMap.isActive("quit") || event.type == sf::Event::Closed)
{
window.close();
return 0;
}
}
// Poll the window for new events, update actions
keyMap.update(window);
if (keyMap.isActive("DownLeft")) {
animationText.setString("(Walk Down-Left)");
playAnimation(animator, "walkDownLeft", event.key.code, animationText);
}
else if (keyMap.isActive("UpLeft")) {
animationText.setString("(Walk Up-Left)");
playAnimation(animator, "walkUpLeft", event.key.code, animationText);
}
else if (keyMap.isActive("DownRight")) {
animationText.setString("(Walk Down-Right)");
playAnimation(animator, "walkDownRight", event.key.code, animationText);
}
else if (keyMap.isActive("UpRight")) {
animationText.setString("(Walk Down-Right)");
playAnimation(animator, "walkUpRight", event.key.code, animationText);
}
else if (keyMap.isActive("Down")) {
animationText.setString("(Walk Down)");
playAnimation(animator, "walkDown", event.key.code, animationText);
}
else if (keyMap.isActive("Left")) {
animationText.setString("Walk Left");
playAnimation(animator, "walkLeft", event.key.code, animationText);
}
else if (keyMap.isActive("Up")) {
animationText.setString("Walk Up");
playAnimation(animator, "walkUp", event.key.code, animationText);
}
else if (keyMap.isActive("Right")) {
animationText.setString("Walk Right");
playAnimation(animator, "walkRight", event.key.code, animationText);
}
else {
animator.stop();
}
// Update animator and apply current animation state to the sprite
animator.update(frameClock.restart());
animator.animate(sprite);
// Draw everything
window.clear(sf::Color(50, 50, 50));
window.draw(animationText);
window.draw(sprite);
window.display();
}
}