0

I have read about an interpolation applied to game loops and tried to implement it myself. It looks almost same as I expected, but when the object ends its movement weird step back takes place. I decided to paste here full source, because this problem may be caused by everything.

#include <SFML/Graphics.hpp>
#include <chrono>

sf::RenderWindow window(sf::VideoMode(800, 600), "Interpolation");
sf::Event event;
int fps = 10; // set to 10 for testing purpose
std::chrono::nanoseconds timePerFrame = std::chrono::seconds(1);
std::chrono::nanoseconds accumulator;
std::chrono::steady_clock::time_point start;
sf::RectangleShape shape1(sf::Vector2f(50, 50));
sf::RectangleShape shape2(sf::Vector2f(50, 50));
sf::Vector2f movement(0, 0);
sf::Vector2f position1(375, 100);
sf::Vector2f position2(375, 275);

void initialization();
void processInput();
void update();
void interpolate();
void render();

int main()
{
    initialization();
    while(window.isOpen())
    {
        start = std::chrono::steady_clock::now();
        processInput();
        while(accumulator >= timePerFrame)
        {
            update();
            accumulator -= timePerFrame;
        }
        interpolate();
        render();
        accumulator += std::chrono::steady_clock::now() - start;
    }
    return 0;
}

void initialization()
{
    timePerFrame /= fps;
    shape1.setPosition(position1);
    shape2.setPosition(position2);
}

void processInput()
{
    while(window.pollEvent(event))
    {
        if(event.type == sf::Event::Closed) window.close();
    }
}

void update()
{
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) movement = sf::Vector2f(-300, 0);
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) movement = sf::Vector2f(300, 0);
    else movement = sf::Vector2f(0, 0);
    position1.x += movement.x / fps;
    position2.x += movement.x / fps;
    shape1.setPosition(position1);
    shape2.setPosition(position2);
}

void interpolate()
{
    double interpolationFactor = (double) accumulator.count() / timePerFrame.count();
    shape2.setPosition(position2.x + (movement.x / fps * interpolationFactor), position2.y);
}

void render()
{
    window.clear(sf::Color::Black);
    window.draw(shape1);
    window.draw(shape2);
    window.display();
}

I do not know what may cause that kind of problem. I'm looking forward your help.

1 Answers1

0

Your interpolate function can count some parts of the time interval multiple times.

Since accumulator only resets every timePerFrame ticks, a fast loop rate can add smaller intervals multiple times. If the main loop runs in 0.01 seconds, the first call to interpolate uses that 0.01 in the interpolation factor. The next time, it uses 0.02 (for a total add of 0.03). This continues until there is enough time accumulated for update to update the position using 0.1 seconds (the time step). Since interpolate added in more time than that, the object jumps back.

interpolate should only add in the time of the current step, and not the fully accumulated time. (Also, rather than calling now to get the start time every loop, the previous loop's now value used for the end time should be used as the start time for the next loop. Otherwise you'll lose occasional clock ticks when it changes between the end of one loop and the start of the next.)

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • Thanks for the quick reply. From your answer I understand a few things. I mean adding a new variable that contains a time point at the end of the main loop is a good idea. But I do not know what you mean by "adding in the current step". In the link below there is a picture which describes what is my way of thinking. I mean interpolated position should not be greater then that one which is set while next frame. http://i.imgur.com/jGa2Hyw.png – Naul Pewman Sep 08 '17 at 17:17
  • @NaulPewman The `interpolate` function should only add in the time interval of the current step - the amount you're adding to `accumulator`. In other words, since it has already accounted for the time up to the last call to `interpolate`, it only wants to factor in the time that has elapsed since then. – 1201ProgramAlarm Sep 08 '17 at 20:05
  • Could you post some examle code how should it work? It would be better to imagine it then. – Naul Pewman Sep 09 '17 at 08:27