Анимация спрайтов в sfml с листа спрайтов

Я пытаюсь оживить спрайт в sfml. В настоящий момент я могу перемещать спрайт и изменять его изображение при перемещении в другом направлении, но я хочу анимировать его во время движения. Я думаю, что может быть способ сделать это с помощью sf :: Clock или может быть лучший способ. Все спрайты находятся на одном и том же листе спрайтов, поэтому мне просто нужно найти способ изменить координаты X и Y textureRect в зависимости от времени при движении в направлении. Если я что-то упустил или у вас есть какие-либо вопросы, я отвечу в меру своих возможностей.

main.cpp

#include <iostream>
#include <SFML/Graphics.hpp>
#include "Character.hpp"
int main() {
sf::RenderWindow window(sf::VideoMode(5000, 5000), "Awesome Game" );
Character Boi("SpritesBoi.png", 0, 0, 5, 100);
sf::Sprite BoiSprite = Boi.getSprite();
Boi.SheetX = 0;
Boi.SheetY = 48;

while (window.isOpen()){

// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event)){
// "close requested" event: we close the window
if (event.type == sf::Event::Closed){
window.close();
}
}

Boi.Move();
BoiSprite.setTextureRect(sf::IntRect(Boi.SheetX, Boi.SheetY, 110, 150));
BoiSprite.setPosition(Boi.x_pos, Boi.y_pos);
window.clear(sf::Color(255, 255, 255));
window.draw(BoiSprite);
window.display();
}

}

Character.hpp

#ifndef Character_hpp
#define Character_hpp

#include <stdio.h>
#include <SFML/Graphics.hpp>
#endif /* Character_hpp */

class Character{
public:
int health;
int speed;
int x_pos;
int y_pos;
int SheetX;
int SheetY;
sf::Texture texture;
sf::Sprite sprite;

Character(std::string image, int xlocation, int ylocation, int s, int h){
health = h;
speed = s;
x_pos = xlocation;
y_pos = ylocation;
texture.loadFromFile(image);
}
sf::Sprite getSprite() {
sprite.setTexture(texture);
sprite.setPosition(x_pos, y_pos);
sprite.setTextureRect(sf::IntRect(SheetX, SheetY, 110, 150));
return sprite;
}

void Move();

};

Character.cpp

#include "Character.hpp"#include <iostream>
void Character::Move(){//Up
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
SheetX = 0;
SheetY = 192;
y_pos = y_pos - 1;
Up = true;

}
//Down
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){
SheetX = 0;
SheetY = 48;
y_pos = y_pos + 1;
Down = false;

}
//Left
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
SheetX = 0;
SheetY = 480;
x_pos = x_pos - 1;
Left = true;

}
//Right
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
SheetX = 0;
SheetY = 339;
x_pos = x_pos + 1;
Right = true;

}
//Up Right
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) and sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
SheetX = 334;
SheetY = 490;

}
//Up Left
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) and sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
SheetX = 333;
SheetY = 340;
}
//Down Right
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) and sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
SheetX = 334;
SheetY = 48;
}
//Down Left
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) and sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
SheetX = 334;
SheetY = 191;
}

}

0

Решение

Вы должны отслеживать кадры в анимации (список sf :: IntRects). И есть какая-то задержка между ними. При обновлении просто перемещайтесь по рамкам и применяйте прямоугольник.

struct Frame {
sf::IntRect rect;
double duration; // in seconds
};

class Animation {
std::vector<Frame> frames;
double totalLength;
double totalProgress;
sf::Sprite *target;
public:
Animation(sf::Sprite& target) {
this->target = &target;
totalProgress = 0.0;
}

void addFrame(Frame&& frame) {
frames.push_back(std::move(frame));
totalLength += frame.duration;
}

void update(double elapsed) {
totalProgress += elapsed;
double progress = totalProgress;
for(auto frame : frames) {
progress -= (*frame).duration;

if (progress <= 0.0 || &(*frame) == &frames.back())
{
target->setTextureRect((*frame).rect);
break; // we found our frame
}
}
};

Вы можете использовать так:

sf::Sprite myCharacter;
// Load the image...
Animation animation(myCharacter);
animation.addFrame({sf::IntRect(x,y,w,h), 0.1});
// do this for as many frames as you need

// In your main loop:
animation.update(elapsed);
window.draw(myCharacter);
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]