Im writing MK clone.
I wrote Animation class:
#ifndef ANIMATOR_H
#define ANIMATOR_H
#include <vector>
#include "SFML\Graphics.hpp"
class Animator {
public:
Animator();
~Animator();
void addFrame(sf::IntRect frame);
void play(sf::Time duration, bool loop);
bool isPlaying() const;
void update(sf::Time delta);
// Sprite contains current frame
void switchFrame(sf::Sprite& sprite);
private:
std::vector<sf::IntRect> _frames;
unsigned _currentFrame;
bool _loop;
bool _isPlaying;
sf::Time _duration;
};
#include "Animator.h"
Animator::Animator() : _currentFrame(0), _isPlaying(false), _duration(sf::Time::Zero), _loop(false) {}
Animator::~Animator() {
}
void Animator::addFrame(sf::IntRect frame) {
_frames.push_back(frame);
}
void Animator::play(sf::Time duration, bool loop) {
_isPlaying = true;
_duration = duration;
_loop = loop;
}
bool Animator::isPlaying() const {
return _isPlaying;
}
void Animator::update(sf::Time delta) {
if (!isPlaying())
return;
// Local time buffer
static sf::Time buffer = sf::Time::Zero;
// Update with an elapsed time
buffer += delta;
// Compute single frame duration
sf::Time frameDuration = _duration / static_cast<float>(_frames.size());
// Time to switch frame
if (buffer >= frameDuration) {
_currentFrame++;
// If looping animation is not allowed
if (_currentFrame >= _frames.size()) {
if (!_loop)
_isPlaying = false;
_currentFrame = 0;
}
buffer -= frameDuration;
}
printf("%d\n", _currentFrame);
}
void Animator::switchFrame(sf::Sprite& sprite) {
sprite.setTextureRect(_frames[_currentFrame]);
}
#endif // ANIMATOR_H
And in raiden's class derived from Character class, with is derived from Transformable and Drawable, created 2 animators: idle and idle_electricity.
I wanted them to play simultaneously..
#ifndef RAIDEN_H
#define RAIDEN_H
#include "Character.h"
#include "Animator.h"
class Raiden : public Character {
public:
Raiden();
~Raiden();
virtual void update(sf::Time delta);
private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const;
private:
sf::Texture _spritesheet;
sf::Sprite _visual;
sf::Sprite _visualElectro;
Animator _idle;
Animator _idleElectro;
};
#endif // RAIDEN_H
Raiden::Raiden() {
if (!_spritesheet.loadFromFile("Assets/raiden-s.png"))
throw std::runtime_error("Unable to load raiden's spritesheet");
_visual.setTexture(_spritesheet);
_visualElectro.setTexture(_spritesheet);
setOrigin(27, 51);
setPosition(300, 300);
// Idle animation
for (unsigned i = 1; i <= 271; i += 54)
_idle.addFrame(sf::IntRect(i, 14, 54, 102));
// Idle electricity animation
for (unsigned i = 1; i <= 811; i += 54)
_idleElectro.addFrame(sf::IntRect(i, 132, 54, 102));
_idle.play(sf::seconds(1), true);
_idleElectro.play(sf::seconds(2), true);
}
Raiden::~Raiden() {
}
void Raiden::update(sf::Time delta) {
// Animation update
_idle.update(delta);
_idle.switchFrame(_visual);
_idleElectro.update(delta);
_idleElectro.switchFrame(_visualElectro);
Character::update(delta);
}
void Raiden::draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform *= getTransform();
target.draw(_visual, states);
target.draw(_visualElectro, states);
}
What is strange? (Note printf("%d\n", _currentFrame); in animator update method )
While both of them are being played, only electicity's one animation is playing, but idle's one (raiden itself) stands still without changes.
For idle's one it prints 0 as currentFrame, for electricity's one - normally cycled
But, when electicity's one _loop is being set to false, it's stopped (which is ok), but idle's one starts cycling thru frames.. (animation is played) Why is that ?
+ dont know why, after resizing a window, currentFrame of idle's one changes (when both _loop are being set to true..) I mean, i feel like _idle_electricity's animation depends on time, but _idle's one only to window resizing or window clicks..