从Sprite工作表中的SFML动画精灵 [英] Animating sprites in sfml from a sprite sheet

查看:298
本文介绍了从Sprite工作表中的SFML动画精灵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为sfml中的精灵设置动画。目前,我可以移动精灵并在朝不同方向移动时更改其图像,但是我想在其移动时对其进行动画处理。我认为可能有一种方法可以使用sf :: Clock完成此操作,或者可能有更好的方法。所有的精灵都在同一个精灵表上,因此我只需要找到一种方法即可在一个方向上移动的同时根据时间更改textureRect的X和Y坐标。如果我缺少任何东西或您有任何疑问,我将尽我所能回答。

I am trying to animate a sprite in sfml. At the moment I am able to move the sprite and change it's image when moving in a different direction, but I want to animate it while it is moving. I am thinking that there might be a way to accomplish this with sf::Clock or there might be a better way. All sprites are on the same sprite sheet so I just need to find a way to change the X and Y coordinates of the textureRect based on a time while moving in a direction. If I am missing something or you have any questions, I will answer to the best of my ability.

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

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

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;
    }

}


推荐答案

您需要跟踪动画中的帧(sf :: IntRects列表)。并在两者之间存在某种延迟。在更新时,只需移动框架并应用矩形即可。

You need to keep track of the frames in the animation (list of sf::IntRects). And have some sort of delay inbetween. On update, simply move through the frames and apply the rectangle.

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);

这篇关于从Sprite工作表中的SFML动画精灵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆