Question

Lets say I have 4 images and I want to use these 4 images to animate a character. The 4 images represent the character walking. I want the animation to repeat itself as long as I press the key to move but to stop right when I unpress it. It doesn't need to be SFML specific if you don't know it, just basic theory would really help me.

Thank you.

Was it helpful?

Solution

You may want some simple kind of state machine. When the key is down (see sf::Input's IsKeyDown method), have the character in the "animated" state. When the key is not down, have the character in "not animated" state. Of course, you could always skip having this "state" and just do what I mention below (depending on exactly what you're doing).

Then, if the character is in the "animated" state, get the next "image" (see the next paragraph for more details on that). For example, if you have your images stored in a simple 4 element array, the next image would be at (currentIndex + 1) % ARRAY_SIZE. Depending on what you are doing, you may want to store your image frames in a more sophisticated data structure. If the character is not in the "animated" state, then you wouldn't do any updating here.

If your "4 images" are within the same image file, you can use the sf::Sprite's SetSubRect method to change the portion of the image displayed. If you actually have 4 different images, then you probably would need to use the sf::Sprite's SetImage method to switch the images out.

OTHER TIPS

How would you enforce a framerate so that the animation doesn't happen too quickly?

Hello please see my answer here and accept this post as the best solution.

https://stackoverflow.com/a/52656103/3624674

You need to supply duration per frame and have the total progress be used to step through to the frame.

In the Animation source file do

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) {
        // increase the total progress of the animation
        totalProgress += elapsed;

        // use this progress as a counter. Final frame at progress <= 0
        double progress = totalProgress;
        for(auto frame : frames) {
           progress -= (*frame).duration;  

          // When progress is <= 0 or we are on the last frame in the list, stop
          if (progress <= 0.0 || &(*frame) == &frames.back())
          {
               target->setTextureRect((*frame).rect);  
               break; // we found our frame
          }
     }
};

To stop when you unpress, simply only animate when the key is held

if(isKeyPressed) {
    animation.update(elapsed); 
}

To support multiple animations for different situations have a boolean for each state

bool isWalking, isJumping, isAttacking;

...

if(isJumping && !isWalking && !isAttacking) {
   jumpAnimation.update(elapsed);
} else if(isWalking && !isAttacking) {
   walkAnimation.update(elapsed);
} else if(isAttacking) { 
   attackAnimation.update(elapsed);
}

...

// now check for keyboard presses
if(jumpkeyPressed) { isJumping = true; } else { isJumping false; }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top