Search code examples
c++sfml

Clunky movement on transformable objects SFML


So I am working on a game in SFML and am having a weird problem with movement. I have implemented a delta time so the movement speed is constant but I have this weird issue where I press a move key, the object jumps by speed units, pauses, then proceeds to move smoothly. I haven't been able to find much on this as I don't really know what problems I should be looking for. Here is a copy of my current code.

#include <SFML/Graphics.hpp>
#include "Player.h"
#include <iostream>
#include <vector>

void handleKeyPress(sf::Event &event, Player &player, float dt);

int main() {

    sf::ContextSettings settings;

    settings.antialiasingLevel = 16;

    sf::RenderWindow window(sf::VideoMode(800, 600), "Title", sf::Style::Default, settings);

    sf::Event event;

    Player player;

    player.setPosition(100, 100);

    sf::Clock dtClock;

    while (window.isOpen()) {

        

        float dt = dtClock.getElapsedTime().asSeconds();
    
        while (window.pollEvent(event)) {
        
            if (event.type == sf::Event::Closed) {
    
                window.close();
    
            }

            handleKeyPress(event, player, dt);
    
            window.clear(sf::Color::Black);

            //drawing happens hear

            window.draw(player);

            //end of frame
            window.display();

            dtClock.restart();

        }
    }
}

void handleKeyPress(sf::Event& event, Player& player, float dt) {

    sf::Vector2f moveVector(0.0f, 0.0f);

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
        moveVector.x = -player.speed;
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
        moveVector.x = player.speed;
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
        moveVector.y = -player.speed;
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
        moveVector.y = player.speed;

    player.move(moveVector * dt);
}

Note that player is just an SFML Transformable object/drawable object.


Solution

  • Your main is mixing event processing and state updates with drawing, which makes it hard to respect the fractional updates you intend to do with dt. The code below undoes that: it first eats all events, then updates the game state, then draws.

    In order to have smooth movement, you need to remember the Player velocity depending on which keys are pressed/released:

    • Add a velocity vector to Player
    • Change handleKeyPress to modify the velocity appropriately. Pay attention to multiple keypresses, eg up + right = (+1, +1)
    • Add an update method to player that adds a dt fraction of velocity to position.

    Change it to:

    while (window.isOpen()) {
    
        float dt = dtClock.getElapsedTime().asSeconds();
    
        // process events
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            } else if (event.type == sf::Event::KeyPressed || event.type == sf::Event::KeyReleased) {
                // rewrite this to update player.velocity depending on what key is pressed if released
                handleKeyPress(event, player, dt);
            }
        }
    
        // apply dt * player.velocity to player.position
        player.update(dt);
    
        // draw
        window.clear(sf::Color::Black);
        //drawing happens hear
        window.draw(player);
    
        // restart the dtclock here, as display() will pause for a bit
        dtClock.restart();
    
        //end of frame
        window.display();
    }