Try something along the lines of this:
void update(sf::Time delta_time) {
// advance the simulation - taking delta_time into account. For example:
auto distance_to_move_this_frame = velocity * delta_time.asSeconds();
stuff.move(distance_to_move_this_frame);
}
const sf::Time timestep = sf::seconds(1.f) / 40.f; // take one physics step / simulation step every 1 fourtieth of a second
sf::Time remainder_time = sf::seconds(0.f); // left over time from previous frame(s)
sf::Time elapsed_time = sf::seconds(0.f);
sf::Clock clock;
window.setFramerateLimit(60); // render at aproximately 60 fps
while (whindow.isOpen()) { // our main game loop
// ... event handling goes here ...
elapsed_time = clock.restart(); // figure out how much time passed since last frame
elapsed_time += remainder_time; // add the time we have left over and not yet accounted for
while (elapsed_time >= timestep) { // as long as enough time has passed that we need to take a step to keep up ..
update(timestep); // update simulation; pass in timestep so it can scale based on passed time
elapsed_time -= timestep; // we just took a step so subtract the time one represents
}
remainder_time = elapsed_time; // whatever is left in elapsed_time is our remainder for the next frame
window.clear(); // clear the screen in preparation for rendering the current frame
window.draw(stuff); // render the current state of the simulation
window.display(); // put it on the screen
}
The above example code has a number of advantages over what you posted above:
1) Every update advances the simulation by the exact same amount of time. This gives you reproducibility; if you replay a simulation from time
T to
T + N you'll always take the exact number of steps and the result after each step is deterministic (and since the update() function takes the actual value of delta_time into account it's easy to experiment with changing the timestep).
2) Updating by a fixed amount of time each step let's you guarantee such things as "my player cannot ever move entirely through a wall in a single update without me detecting it" and "I'll never overflow this calculation since I know the time/distance/whatever is always within this bound for each discreet step" etc.
3) The loop above takes as many steps as needed (or none) to catch the simulation up to real time and (
crucially) it remembers the time-not-simulated-this-frame for the next one so that the simulation does not leak time and does always eventually catch up with (or at least stays close to) real-time and does not fall more and more behind.
4) it completely decouples simulation update from rendering - the two can happen at completely different intervals (as long as the simulation can keep up) and you don't depend on the
actual frame rate to achieve smooth movement/simulation progress.
How you choose to step your simulation forward based on the time passed (the timestep) is up to you and how precise you want it to be of course. You can do simple Euler integration (which is not great but simple and perfectly fine for a lot of simple stuff) or you can go with Verlet or RK4 if you need more accuracy. But that's a completely different thing from keeping the timestep fixed and updating frame-rate independent and and not "leaking" time.
Also; what I present above is not perfect. It can be improved in various ways; like using the remainder_time to interpolate between the current and next frame and other tricks. But it's usually good enough for most simple (and not so simple) use cases in my experience.
I hope that made sense and was useful/helpful. If not; feel free to ask.
And if someone on the forum can find faults with the above; please do correct me.