thor::Animator 只播放一帧
thor::Animator playing only one frame
我一直在尝试使用雷神 2.1 为 sf::Sprite 制作动画,但截至目前,我的 sprite 只显示每个动画的一帧,而不是遍历所有动画。
我从 SFML 的 spritesheets 教程中得到了一个示例 spritesheet:
我的代码(原理图代码,不全):
#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;
}
正如我所说,该代码的行为是它只播放向上动画的第一帧(在本例中是 spritesheet 的左上帧)。
对于 "left" 动画,它播放第二行的第一帧,并分别播放所有其他帧。
首先,
texPlayer.create(96, 128);
不需要,因为您会立即加载文件并因此覆盖纹理。 sf::Texture::create()
主要用于加载后编辑纹理,或用于低级 OpenGL。
thor::Animator
可以理解为有两种操作模式,每一种都涵盖了几个方法:
- Select/switch 动画:
play()
, stop()
, queue()
仅当您想要更改正在播放的动画(角色开始 move/attack)或想要停止正在播放的动画(角色静止不动)时才应调用此方法。
- 更新状态并应用图形:
update()
, animate()
这应该应用于每个图形帧。如果你想要确定性的动画行为(你的动画需要不断的进步),你应该在固定时间的逻辑步骤中调用 update()
。
这些已经是thor::Animator
提供的所有方法,参见official documentation。
您的代码中的错误是您在每一帧都调用了 play()
,从而不断地重新启动动画。您应该做的是在 while
循环之前调用 play()
。由于您指定了 thor::Playback::loop()
,只要您更新动画器,动画就会循环播放。
我一直在尝试使用雷神 2.1 为 sf::Sprite 制作动画,但截至目前,我的 sprite 只显示每个动画的一帧,而不是遍历所有动画。
我从 SFML 的 spritesheets 教程中得到了一个示例 spritesheet:
我的代码(原理图代码,不全):
#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;
}
正如我所说,该代码的行为是它只播放向上动画的第一帧(在本例中是 spritesheet 的左上帧)。
对于 "left" 动画,它播放第二行的第一帧,并分别播放所有其他帧。
首先,
texPlayer.create(96, 128);
不需要,因为您会立即加载文件并因此覆盖纹理。 sf::Texture::create()
主要用于加载后编辑纹理,或用于低级 OpenGL。
thor::Animator
可以理解为有两种操作模式,每一种都涵盖了几个方法:
- Select/switch 动画:
play()
,stop()
,queue()
仅当您想要更改正在播放的动画(角色开始 move/attack)或想要停止正在播放的动画(角色静止不动)时才应调用此方法。 - 更新状态并应用图形:
update()
,animate()
这应该应用于每个图形帧。如果你想要确定性的动画行为(你的动画需要不断的进步),你应该在固定时间的逻辑步骤中调用update()
。
这些已经是thor::Animator
提供的所有方法,参见official documentation。
您的代码中的错误是您在每一帧都调用了 play()
,从而不断地重新启动动画。您应该做的是在 while
循环之前调用 play()
。由于您指定了 thor::Playback::loop()
,只要您更新动画器,动画就会循环播放。