user2445611
user2445611

Reputation: 11

How to move a sprite smoothly?

I have written a simple program with C++ and SFML. My problem is that when i move my sprite it is very choppy. My sprite will move a little then accelerate to a smooth movement until I press another key and it will stop again then continue. I hope this makes sense but in short I just want my sprite movement to be smoother. My code:

#include <SFML/Graphics.hpp>
#include <math.h>
#include <iostream>

int main()
{
    float x = 0;
    float y = 0;
    sf::Vector2f position;
    sf::Vector2f velocity;
    float maxspeed = 3.0f;
    float accel = 1.0f;
    float decel = 0.02f;
    sf::RenderWindow window(sf::VideoMode(400, 400), "SFML works!");
    sf::Texture tplayer;

    if (!tplayer.loadFromFile("character.png"))
    {
        // error...
    }

    sf::Sprite splayer;
    splayer.setTexture(tplayer);
    splayer.setOrigin(sf::Vector2f(0, 0));
    splayer.setTextureRect(sf::IntRect(0, 0, 16, 38));

    sf::Vector2f pos = splayer.getPosition();

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            {
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                    velocity.x -= accel;
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                    velocity.x += accel;
                else
                    velocity.x *= decel;

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                    velocity.y -= accel;
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                    velocity.y += accel;
                else
                    velocity.y *= decel;

                if (velocity.x < -maxspeed) velocity.x = -maxspeed;
                if (velocity.x > maxspeed)  velocity.x = maxspeed;
                if (velocity.y < -maxspeed) velocity.y = -maxspeed;
                if (velocity.y > maxspeed)  velocity.y = maxspeed;

                position += velocity;
                splayer.setPosition(position);
            }
        }

        window.clear();
        window.draw(splayer);
        window.display();
        window.setFramerateLimit(60);
    }

    return 0;
}

Upvotes: 1

Views: 1751

Answers (2)

jkbz64
jkbz64

Reputation: 180

Google frame independent movement

//Before main loopp
sf::Clock clock;

// Start main loop

         //Somewhere in the main loop
         sf::Time deltaTime = clock.restart().asSeconds();
         velocity.x *= deltaTime.asSeconds();
         velocity.y *= deltaTime.asSeconds();
         //move is just a setPosition but it adds given argument to actual position so it's basically splayer.setPosition(sf:Vector2f(position.x + velocity.x,position.y + velocity.y));
         splayer.move(velocity);

Upvotes: 2

Bruno Zell
Bruno Zell

Reputation: 8581

Don't use the sf::Keyboard::isKeyPressed-Method in the poll Event loop! This Method provides a way to ask for a key state anywhere in your program. Only writ code in your poll Event loop if you previously checked that the current polled event is that what you think. You do it like so if(event.type == sf::Event::Closed) as you already found out. So just move all of your code (except for the window close event) out of the poll event loop. I have the feeling that you don't understand what exactly the event loop does, so I'll explain it to you: Every event (e.g. mouse event, key pressed, window resize, ...) that occoured in the previous frame is queued and thes poll event loop goes over every queued event. For example first you have the mouse moved event, then a key pressed event. And you only want to do an action once of one specific event is occoured, so you have to ask with this if-block if the current event matches the events it is searched for. And the do sth. once.

Btw: You can call window.setFramerateLimit(60); before the window is even open, so you don't waste reccources on setting the limit each frame.

Upvotes: 0

Related Questions