0
\$\begingroup\$

I'm using GLFW for my window and input related work. I'm calculating delta time and multiplying it with my player speed and then finally adding it to the current position of the player. The thing is that, though it makes my motion frame independent the player movement appears to slow and speed up interchangeably. Well the reason would be the different values of delta time at each frame. What should I do to smooth out this animation?

Here is the relevant code, and a capture of what's going on:

float deltaTime = 0;
float oldTime = 0;

//The direction in which the player will move
int playerX = 0;
int playerY = 0;

//callback method for keyboard events
void keyboard_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
    if (key == GLFW_KEY_W && action == GLFW_REPEAT) {
        playerX = 0; playerY = 1;
    }
    if (key == GLFW_KEY_S && action == GLFW_REPEAT) {
        playerX = 0; playerY = -1;
    }
    if (key == GLFW_KEY_D && action == GLFW_REPEAT) {
        playerX = 1; playerY = 0;
    }
    if (key == GLFW_KEY_A && action == GLFW_REPEAT)
    {
        playerX = -1; playerY = 0;
    }
}

//update player's position
void update() {
    player->move(playerX, playerY, TIME_PER_FRAME);
}

//set up glfw keyboard callback function and other stuff
void init() {
    glClearColor(0, 0, 0, 0);
    player->bindVertexAttributes(shader.getAttributeLocation("position"));
    glfwSetKeyCallback(window->getGLFWWindow(), keyboard_callback);
}


//wait logic 
float expected_frame_end = glfwGetTime() + TIME_PER_FRAME;
void wait() {
    while (glfwGetTime() < expected_frame_end) {

    }
    expected_frame_end += TIME_PER_FRAME;
    playerX = playerY = 0;
}

//rendering function
void render() {
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    player->setUniformMatrixLocation(shader.getUniformLocation("projectionMatrix"), shader.getUniformLocation("transformationMatrix"));
    shader.useProgram();
    update();
    player->render();
    wait();
    shader.stopProgram();
}

//main function
int main(int argc, char** argv) {
    init();
//main loop
    while (!glfwWindowShouldClose(window->getGLFWWindow())) {
        render();
        window->swapBuffers();
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

enter image description here

\$\endgroup\$
1
  • \$\begingroup\$ Why does your delta jitter? Could it be that you are querying system time with not enough precision? There are several ways to query the time. Which one do you use? \$\endgroup\$
    – Kromster
    Aug 19, 2017 at 16:09

1 Answer 1

0
\$\begingroup\$

I'm calculating delta time and multiplying it with my player speed and then finally adding it to the current position of the player.

This is variable timestep, which contradicts how you currently tagged the question: .

If your game can currently run at sky high frame rates like 300hz, this is expected.

This is often fixed by actually fixing the time-step: make sure you run your game at a fixed framerate (like 60hz). This means that you have 1/60th of a second to simulate and draw everything. If your loop takes less time than that, wait. (As in, don't put your thread to sleep.)

I usually like to do something like (pseudo-code):

expected_frame_end = getCurrentTime() + FRAME_TIME

while( true ) {

  update( FRAME_TIME ) // frame time is your delta time, i.e. 1/DESIRED_FRAME_RATE, which is 
                       // constant.

  while ( getCurrentTime() < expected_frame_end )
  {
    // do nothing;
  }
  expected_frame_end += FRAME_TIME

}

Generally, sleep methods guarantee that the thread will be suspended for at least the time you requested, not at most, which results in frames taking longer than expected, and variation in your actual frame rate.

I suggest a nice read: Fix Your Timestep!.


Is it has to the way keyboard input is processed or something else?[sic]

Maybe!

The input received by an application largely depends on what the OS decides to send it. And if the app runs at 60Hz, it's most probably too fast for the OS, as in: the OS will not send input 60 times per second, but less often.

To work around that, when you expect the keys/mouse buttons to be held down, you have to register when the key is pressed down, and when it's released. Your code that acts on "key down" will only check your local variable "isKeyDown".

So you need a software layer that checks the state changes sent by the OS, and your code interacts with that layer instead of interacting directly with the raw input sent by the OS.

\$\endgroup\$
5
  • \$\begingroup\$ Thanks That makes it move at a constant speed. But It still looks like instead of smoothly moving it appears to jump small small steps. Is it has to the way keyboard input is processed or something else? And it becomes apparent when the speed of the player is increased \$\endgroup\$ Aug 19, 2017 at 16:47
  • \$\begingroup\$ You'd have to add an animated gif to your question, and show the code for the movement, the input and the main loop. \$\endgroup\$
    – Vaillancourt
    Aug 19, 2017 at 22:43
  • \$\begingroup\$ I've post below the code and a gif animation in the answer below \$\endgroup\$ Aug 20, 2017 at 6:30
  • \$\begingroup\$ @JitendraTiwari See my updated answer. \$\endgroup\$
    – Vaillancourt
    Aug 20, 2017 at 12:36
  • \$\begingroup\$ Thanks! Adding extra software layer instead of getting them directly from os does help!!! \$\endgroup\$ Aug 20, 2017 at 13:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .