SFML community forums

Help => System => Topic started by: MediocreVeg1 on January 05, 2021, 09:37:50 am

Title: [SOLVED] Frame-independent movement with sf::Clock
Post by: MediocreVeg1 on January 05, 2021, 09:37:50 am
I've tried to implement frame-independent movement for my player, and it should be working, but I'm still seeing slowdown in player movement.

Not sure if this is relevant to the question, but for my player I'm using tile movement (Basically when you press a direction key the player will move a fixed distance over a few frames until it reaches the next tile. When I press a direction key, the player's clock is restarted and a bool isMoving is set to true until the player reaches the next tile. With that said, here's just a minimal example of where I've used the clock for frame-independent movement:

if (isMoving)
{
    if (clock.getElapsedTime().asSeconds() > (1 / 30))
    {
        move(/* For now this is 2 pixels in the desired direction */);
        movePixelsLeft -= speed; // when this reaches 0 it means the player has reached the next tile
        clock.restart();
    }
    if (movePixelsLeft <= 0)
    {
        isMoving = false;
        if (getColMapPosNum() > 1)
        {
            isMoving = false;
            // some other stuff
        }
    }
}
 

On a side note, my game seems to be unable to go over 40FPS, is there anything i can do to improve performance?
Title: Re: Frame-independent movement with sf::Clock
Post by: Laurent on January 05, 2021, 10:11:54 am
A common and simple solution is to choose a fixed speed (in units/s) and then move the player by speed * elapsed_time every frame.

There are two problems with your implementation:
1. you move only once every N frames; movement would be smoother if you moved every frame
2. you move by a constant amount of pixels when time is > 0.033, but it could be any value, not exactly 0.033, so the result is a variable speed
Title: Re: Frame-independent movement with sf::Clock
Post by: MediocreVeg1 on January 05, 2021, 10:34:57 am
Addressing Point 1: Before this, I did originally move 2 pixels every frame, but since my game is sometimes suffering from frame drops, it ends up affecting player speed.  When the game starts, the FPS also takes a few seconds to reach about 35-40FPS, so the player is much slower during that time

Quote
A common and simple solution is to choose a fixed speed (in units/s) and then move the player by speed * elapsed_time every frame.

Problem is, I have to move exactly 48 pixels (the size of a tile), so since the elapsed time could vary, the player might end up in-between tiles.

[EDIT] I added an fps counter to my game and indeed, the player slows down when the frame-rate drops significantly
Title: Re: Frame-independent movement with sf::Clock
Post by: Laurent on January 05, 2021, 11:41:18 am
Quote
Problem is, I have to move exactly 48 pixels (the size of a tile), so since the elapsed time could vary, the player might end up in-between tiles.
There are simple solutions to this problem. Like storing the distance walked by the player, and clamping the last move so that it never exceeds 48.

auto frame_distance = speed * elapsed_time;
if (frame_distance + total_distance > 48)
{
    frame_distance = 48 - total_distance;
    is_moving = false;
}

total_distance += frame_distance;
move(frame_distance);
Title: Re: Frame-independent movement with sf::Clock
Post by: MediocreVeg1 on January 05, 2021, 01:06:46 pm
That worked, thanks a lot   ;D