Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Sprite Animation Speed Ridiculously Fast  (Read 14609 times)

0 Members and 1 Guest are viewing this topic.

andrewhopps

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Sprite Animation Speed Ridiculously Fast
« on: July 17, 2013, 07:48:19 am »
I have looked all over for hours trying to find some type of working solution to why my sprite animation moves faster than my eyes can even recognize. Can anybody give me code that will make it look like the guy is walking instead of running like Flash?

I followed CME tutorials on youtube, but I must be seriously missing something. If you by any chance post a separate class, could you indicate how to incorporate it into the main.

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <string>
#include <iostream>

int main()
{
    enum Direction { Down, Left, Right, Up };

    sf::Vector2i screenDimensions(800,600);

    sf::RenderWindow window(sf::VideoMode(screenDimensions.x, screenDimensions.y), "SFML Game");

    float frameCounter = 0, switchFrame = 100, frameSpeed = 500;

    sf::Texture pTexture;
    sf::Sprite playerImage;
    sf::Clock clock;
    sf::Font font;
    sf::Music music;

    sf::Vector2i source(1, Down);

    {
    if(!music.openFromFile("KingOfTheDesert.ogg"))
        std::cout << "Error: Could not locate music file." << std::endl;
    }

    {
    if(!font.loadFromFile("Gabriola.ttf"))
        std::cout << "Error: Could not locate the font file." << std::endl;
    }

    {
    if(!pTexture.loadFromFile("Player.png"))
        std::cout << "Error: Could not load player image." << std::endl;
    else
        playerImage.setTexture(pTexture);
    }

    while (window.isOpen())
    {
        sf::Event Event;
        while (window.pollEvent(Event))
        {
            switch(Event.type)
            {
            case sf::Event::Closed:
                window.close();
            case sf::Event::KeyPressed:
                if(Event.key.code == sf::Keyboard::Up)
                    source.y = Direction::Up;
                else if(Event.key.code == sf::Keyboard::Down)
                    source.y = Direction::Down;
                else if(Event.key.code == sf::Keyboard::Left)
                    source.y = Direction::Left;
                else if(Event.key.code == sf::Keyboard::Right)
                    source.y = Direction::Right;
                if(Event.key.code == sf::Keyboard::P)
                    music.play();
                if(Event.key.code == sf::Keyboard::Escape)
                    window.close();
            }
        }

        source.x++;

        if(source.x * 32 >= pTexture.getSize().x)
            source.x = 0;

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            source.y = Up;
            playerImage.move(0, -1);
        }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            source.y = Down;
            playerImage.move(0, 1);
        }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            source.y = Right;
            playerImage.move(1, 0);
        }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            source.y = Left;
            playerImage.move(-1, 0);
        }

        frameCounter += frameSpeed * clock.restart().asSeconds();
        if(frameCounter >= switchFrame)
        {
            source.x++;

            if(source.x * 32 >= pTexture.getSize().x)
                source.x = 0;

            frameCounter = 0;
        }

        playerImage.setTextureRect(sf::IntRect(source.x * 32, source.y * 32, 32, 32));
        window.clear();
        window.draw(playerImage);
        window.display();
    }
    return 0;
}
 

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10936
    • View Profile
    • development blog
    • Email
AW: Sprite Animation Speed Ridiculously Fast
« Reply #1 on: July 17, 2013, 09:16:21 am »
If I read that right, you're running the animation with 500 frames per second, which is obviously waaaay too fast. Maybe try setting the framespeed lower? ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

andrewhopps

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Sprite Animation Speed Ridiculously Fast
« Reply #2 on: July 17, 2013, 09:30:53 am »
I set it to 1 and get the same exact result. It is just not affecting it at all.

massive_potato

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Sprite Animation Speed Ridiculously Fast
« Reply #3 on: July 17, 2013, 11:10:18 am »
Quote
     
  if(Event.key.code == sf::Keyboard::Escape)
                    window.close();
            }
        }

        source.x++;

        if(source.x * 32 >= pTexture.getSize().x)
            source.x = 0;

Remove the line 'source.x++;' from this code snippet. From a brief look-over of your code, this seems to be the problem. You're advancing the x value every single frame, even though you want to advance it only when enough time has passed for each frame to be noticeable. I haven't actually run your code, so no promises on this fixing your problem, but from what I can tell this is the issue.

gostron

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: Sprite Animation Speed Ridiculously Fast
« Reply #4 on: July 17, 2013, 11:25:47 am »
Hey,

Been looking at your code and I don't understand your framerate limit. You just define a framerate which you never use to actually limit the framerate but only in your calculation of frames passed (for your animation). SFML offers a framerate limit so you might want to use it or actually limit the framerate by sleeping a bit?

I also agree with massive_potato, in your code you increment twice source.x, once in every frame and once in a certain number of frames.

I would recommend using time counting before changing every frame (a counter which you increment by the time passed at every frame in milliseconds and when it is superior to 300 ms for example, change your animation) or incrementing a counter by one at every frame (so every loop) and then change it every X frames, but that would require to limit the fps (as opposed to the other method).

Hope I helped you and I didn't say anything wrong ^^

andrewhopps

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Sprite Animation Speed Ridiculously Fast
« Reply #5 on: July 17, 2013, 12:01:28 pm »
massive_potato: That was the issue! So thank you very much for pointing that out.

gostron: I am not exactly well versed in SFML, so let me take a shot at understanding what I should be doing with that counter.

By time passed, are you referring to the time between frames in ms?

Either way, when the passed time is greater than 300ms for example, I would then source.x++?
« Last Edit: July 17, 2013, 12:26:35 pm by andrewhopps »

gostron

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: Sprite Animation Speed Ridiculously Fast
« Reply #6 on: July 17, 2013, 12:21:32 pm »
Yep, that's exactly what I meant. Sorry for the quick explanation

andrewhopps

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Sprite Animation Speed Ridiculously Fast
« Reply #7 on: July 17, 2013, 12:28:02 pm »
Perhaps a snippet of an example? Just tinkering with my current code after removing the extra source.x++ gives me an appropriate speed, and I do not have any idea how to properly set up the clock to get the elapsed time to put into an equation to progress my animation. So if you don't mind clarifying that, I would greatly appreciate it. :)

It can be bare minimum not even in proper context, just a general layout would help a lot!
« Last Edit: July 17, 2013, 12:30:16 pm by andrewhopps »

gostron

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: Sprite Animation Speed Ridiculously Fast
« Reply #8 on: July 17, 2013, 12:44:33 pm »
I am at work so give me time to download CodeBlocks and make you something pretty ^^

gostron

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: Sprite Animation Speed Ridiculously Fast
« Reply #9 on: July 17, 2013, 12:53:16 pm »
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <string>
#include <iostream>

int main()
{
    enum Direction { Down, Left, Right, Up };

    sf::Vector2i screenDimensions(800,600);

    sf::RenderWindow window(sf::VideoMode(screenDimensions.x, screenDimensions.y), "SFML Game");

    int animationCounter = 0, animationFrameDuration = 300;

    sf::Texture pTexture;
    sf::Sprite playerImage;
    sf::Clock clock;
    sf::Font font;
    sf::Music music;

    sf::Vector2i source(1, Down);

    {
    if(!music.openFromFile("KingOfTheDesert.ogg"))
        std::cout << "Error: Could not locate music file." << std::endl;
    }

    {
    if(!font.loadFromFile("Gabriola.ttf"))
        std::cout << "Error: Could not locate the font file." << std::endl;
    }

    {
    if(!pTexture.loadFromFile("Player.png"))
        std::cout << "Error: Could not load player image." << std::endl;
    else
        playerImage.setTexture(pTexture);
    }

    clock.restart();
    while (window.isOpen())
    {
        sf::Event Event;
        while (window.pollEvent(Event))
        {
            switch(Event.type)
            {
            case sf::Event::Closed:
                window.close();
            case sf::Event::KeyPressed:
                if(Event.key.code == sf::Keyboard::Up)
                    source.y = Direction::Up;
                else if(Event.key.code == sf::Keyboard::Down)
                    source.y = Direction::Down;
                else if(Event.key.code == sf::Keyboard::Left)
                    source.y = Direction::Left;
                else if(Event.key.code == sf::Keyboard::Right)
                    source.y = Direction::Right;
                if(Event.key.code == sf::Keyboard::P)
                    music.play();
                if(Event.key.code == sf::Keyboard::Escape)
                    window.close();
            }
        if(source.x * 32 >= pTexture.getSize().x)
            source.x = 0;
        }

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            source.y = Up;
            playerImage.move(0, -1);
        }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            source.y = Down;
            playerImage.move(0, 1);
        }animationCounter
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            source.y = Right;
            playerImage.move(1, 0);
        }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            source.y = Left;
            playerImage.move(-1, 0);
        }
        if(source.x * 32 >= pTexture.getSize().x)
            source.x = 0;

        animationCounter += clock.restart().asMilliseconds();

        if(animationCounter >= animationFrameDuration)
        {
            animationCounter -= animationFrameDuration;
            source.x++;

            if(source.x * 32 >= pTexture.getSize().x)
                source.x = 0;
        }

        playerImage.setTextureRect(sf::IntRect(source.x * 32, source.y * 32, 32, 32));
        window.clear();
        window.draw(playerImage);
        window.display();
    }
    return 0;
}
 


Well I would do something like that, sometimes I replace the if(animationCounter >= animationFrameDuration) by a while so that when we have a very very long frame it doesn't influence the overall animation in a long time perspective (although if you have frames that long this might not be your first concern ^^).

Can't compile it myself so don't hesitate if something is not right

andrewhopps

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Sprite Animation Speed Ridiculously Fast
« Reply #10 on: July 17, 2013, 01:08:49 pm »
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            source.y = Up;
            playerImage.move(0, -1);
        }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            source.y = Down;
            playerImage.move(0, 1);
        }animationCounter                           //Not sure what is going on here?
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            source.y = Right;
            playerImage.move(1, 0);
        }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            source.y = Left;
            playerImage.move(-1, 0);
        }
        if(source.x * 32 >= pTexture.getSize().x)
            source.x = 0;

Not sure what is going on there :p So I just deleted it and it seems to work perfectly :) Thank you so much!
« Last Edit: July 17, 2013, 01:11:26 pm by andrewhopps »

gostron

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: Sprite Animation Speed Ridiculously Fast
« Reply #11 on: July 17, 2013, 01:12:48 pm »
Might have had a wild Ctrl+V going crazy ^^

Good continuation

massive_potato

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Sprite Animation Speed Ridiculously Fast
« Reply #12 on: July 17, 2013, 11:31:40 pm »
If you'd like an animation class, I have one that is fairly easy to use. You'll need to add two files to your project. The first is located here, https://github.com/MassivePotato/SFML_Extensions/blob/master/FlexibleClock.hpp. You won't actually need to use this class. The second file is located here, https://github.com/MassivePotato/SFML_Extensions/blob/master/Animation.hpp. This class handles all of the functions associated with animating a sprite sheet. If you do decide to use it and have any questions, feel free to ask.

Foaly

  • Sr. Member
  • ****
  • Posts: 453
    • View Profile
Re: Sprite Animation Speed Ridiculously Fast
« Reply #13 on: July 17, 2013, 11:39:11 pm »
I also wrote an animation class. It behaves like sf::sprite. It's on the wiki and under the same license as SFML. https://github.com/SFML/SFML/wiki/Source%3A-AnimatedSprite

andrewhopps

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Sprite Animation Speed Ridiculously Fast
« Reply #14 on: July 18, 2013, 12:30:11 am »
Foaly: I have decided to go with yours as it was easiest for me to understand. I want to point out that there was some error in my code with window handling because your code also got rid of an exit error I have been having and posted in another tread! :)

Assuming that it is somewhat efficient, that is the best I could do with my current knowledge. It works completely! Any further improvements would be appreciated, but with some explanation as I really fried my brain figuring that out. :P

I have one issue though, where do I enable the loop for the animation?

#include <SFML/Graphics.hpp>
#include "AnimatedSprite.hpp"

int main()
{
    sf::Vector2i screenDimensions(800,600);
    sf::RenderWindow window(sf::VideoMode(screenDimensions.x, screenDimensions.y), "Animations!");

    // load texture
    sf::Texture texture;
    texture.loadFromFile("Player.png");

    // push frames
    Animation walkingAnimationDown;
    walkingAnimationDown.setSpriteSheet(texture);
    walkingAnimationDown.addFrame(sf::IntRect(0, 0, 32, 32));
    walkingAnimationDown.addFrame(sf::IntRect(32, 0, 32, 32));
    walkingAnimationDown.addFrame(sf::IntRect(64, 0, 32, 32));

    Animation walkingAnimationLeft;
    walkingAnimationLeft.setSpriteSheet(texture);
    walkingAnimationLeft.addFrame(sf::IntRect(0, 32, 32, 32));
    walkingAnimationLeft.addFrame(sf::IntRect(32, 32, 32, 32));
    walkingAnimationLeft.addFrame(sf::IntRect(64, 32, 32, 32));

    Animation walkingAnimationRight;
    walkingAnimationRight.setSpriteSheet(texture);
    walkingAnimationRight.addFrame(sf::IntRect(0, 64, 32, 32));
    walkingAnimationRight.addFrame(sf::IntRect(32, 64, 32, 32));
    walkingAnimationRight.addFrame(sf::IntRect(64, 64, 32, 32));

    Animation walkingAnimationUp;
    walkingAnimationUp.setSpriteSheet(texture);
    walkingAnimationUp.addFrame(sf::IntRect(0, 96, 32, 32));
    walkingAnimationUp.addFrame(sf::IntRect(32, 96, 32, 32));
    walkingAnimationUp.addFrame(sf::IntRect(64, 96, 32, 32));


    // set up AnimatesSprite
    AnimatedSprite animatedSprite(sf::seconds(0.2));
    animatedSprite.setAnimation(walkingAnimationDown);
    animatedSprite.pause();
    animatedSprite.setPosition(0,0);

    sf::Clock frameClock;

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
                window.close();
            if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Up)
            {
                animatedSprite.setAnimation(walkingAnimationUp);
                animatedSprite.play();
            }
            else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Down)
            {
                animatedSprite.setAnimation(walkingAnimationDown);
                animatedSprite.play();
            }
            else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Left)
            {
                animatedSprite.setAnimation(walkingAnimationLeft);
                animatedSprite.play();
            }
            else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Right)
            {
                animatedSprite.setAnimation(walkingAnimationRight);
                animatedSprite.play();
            }
            else
            {
                animatedSprite.pause();
            }
            /*if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::P)
            {
                if(animatedSprite.isPlaying())
                    animatedSprite.pause();
                else
                    animatedSprite.play();
            }*/

        }
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
            {
                animatedSprite.move(0, -.25);
            }
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
            {
                animatedSprite.move(0, .25);
            }
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
            {
                animatedSprite.move(.25, 0);
            }
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
            {
                animatedSprite.move(-.25, 0);
            }
        // update AnimatedSprite
        animatedSprite.update(frameClock.restart());


        window.clear();
        window.draw(animatedSprite);
        window.display();
    }

    return 0;
}

 
« Last Edit: July 18, 2013, 04:10:23 am by andrewhopps »