0
\$\begingroup\$

I'm using glfw's glfwGetTime() function to calculate my time between frames i.e deltaT but when I multiply my desired movement speed by deltaT, and subsequently put that product into my translate vector it moves the character extremely slow.

My fps is right now is around 1300fps average so deltaT should be around 800 microsecond, times my desired speed of 128 units/second I should be able to move my character from 0 to 336 in about 2.6 seconds. But for reference that operation is taking about 20 seconds at the moment.

glfwGetTime() returns a timestamp in seconds... never really seen this happen before if anyone has any idea or further insight about using deltas for input smoothing I would much appreciate.

This is the implementation function for taking a key event and updating the transform matrix.

 void Layer::update(std::deque<Event>* eventStack, double deltaT) { float Vy{0.0f}; float Vx{0.0f}; std::deque<Event>::iterator it = eventStack->begin(); while(it != eventStack->end()) { if((*it).getKey() == GLFW_KEY_UP && ((*it).getAction() == GLFW_PRESS || (*it).getAction() == GLFW_REPEAT)) { Vy += 16.0f;//if specified key event is in stack, do something it = eventStack->erase(it++); //then erase the event from the stack, it's been handled } else if((*it).getKey() == GLFW_KEY_RIGHT && ((*it).getAction() == GLFW_PRESS || (*it).getAction() == GLFW_REPEAT)) { Vx += 16.0f;//if specified key event is in stack, do something it = eventStack->erase(it++); //then erase the event from the stack, it's been handled } else { it++; } } transformation = glm::translate(transformation, glm::vec3(Vx * deltaT, Vy * deltaT, 0.0f)); Vy = 0.0f; Vx = 0.0f; } 

And here is where I calculate my fps and deltaT

void Window::update() { glfwSwapBuffers(_window); glfwPollEvents(); double thisTime = glfwGetTime(); _deltaT = thisTime - _lastTime; _lastTime = thisTime; _elapsedTime += _deltaT; if(_elapsedTime >= 1) { std::stringstream ss; ss << "FPS: " << _frames; glfwSetWindowTitle(_window, ss.str().c_str()); _frames = 0; _elapsedTime = 0; } else { _frames++; } } 
\$\endgroup\$
7
  • 1
    \$\begingroup\$ We need to see your code. Right now it's conflicting statements - you say glfwGetTime returns timestamps in seconds, yet you calculate a 800us deltaT? Also, did you try writing down all deltaT during one second and see how they sum up? \$\endgroup\$ Commented Jan 16, 2022 at 5:58
  • 1
    \$\begingroup\$ Two things come to mind: 1. a unit conversion problem. 2. a timer resolution problem. \$\endgroup\$ Commented Jan 16, 2022 at 11:08
  • \$\begingroup\$ @Kromster the 800us is from taking the timestamp this frame and subtracting the timestamp last frame, which if im running at 1200-1300 fps should be around 0.0008 seconds \$\endgroup\$ Commented Jan 16, 2022 at 15:34
  • \$\begingroup\$ It looks like you're applying your velocity only on frames when you get a new key down (ie. when the key is first pressed, or at an OS-determined repeat rate). This will be much less frequent than once every frame, so you'll get a smaller total displacement. Did you mean to apply your velocity continuously until the key is released? \$\endgroup\$ Commented Jan 16, 2022 at 15:35
  • \$\begingroup\$ @DMGregory yes I did mean for the velocity to be applied every frame until the key is released, which I'm beginning to wonder if this isn't a time issue at all but a difference between event vs polled input. \$\endgroup\$ Commented Jan 16, 2022 at 15:40

1 Answer 1

1
\$\begingroup\$

The issue wasn't actually delta-time related at all, but rather an issue of only updating the velocity when a key event occurred, in discrete steps less frequent than the actual game frame rate.

My solution was to implement an EventHandler class which would still maintain an event buffer as before but also would update a set of booleans for each movement related key. These booleans can be polled at any time so that smooth frame by frame movement can be calculated without losing the ability to have interrupt events such as "press ESC to enter pause menu"

Here is the EventHandler update method

void EventHandler::update() { std::deque<Event>::iterator it = eventStack.begin(); while(it != eventStack.end()) { if((*it).getKey() == KEY_UP) { if((*it).getAction() == KEY_PRESS) { upKeyPressed = true; } if((*it).getAction() == KEY_RELEASE) { upKeyPressed = false; } it = eventStack.erase(it++); } else if((*it).getKey() == KEY_DOWN) { if((*it).getAction() == KEY_PRESS) { downKeyPressed = true; } if((*it).getAction() == KEY_RELEASE) { downKeyPressed = false; } it = eventStack.erase(it++); } else if((*it).getKey() == KEY_LEFT) { if((*it).getAction() == KEY_PRESS) { leftKeyPressed = true; } if((*it).getAction() == KEY_RELEASE) { leftKeyPressed = false; } it = eventStack.erase(it++); } else if((*it).getKey() == KEY_RIGHT) { if((*it).getAction() == KEY_PRESS) { rightKeyPressed = true; } if((*it).getAction() == KEY_RELEASE) { rightKeyPressed = false; } it = eventStack.erase(it++); } else { it++; } } } 

And here it is implemented when we want to move the geometry

void Layer::update(double deltaT) { float Vy{0.0f}; float Vx{0.0f}; if(EventHandler::upKeyPressed) { Vy += 128.0f; } if(EventHandler::downKeyPressed) { Vy -= 128.0f; } if(EventHandler::rightKeyPressed) { Vx += 128.0f; } if(EventHandler::leftKeyPressed) { Vx -= 128.0f; } transformation = glm::translate(transformation, glm::vec3(Vx * deltaT, Vy * deltaT, 0.0f)); Vy = 0.0f; Vx = 0.0f; } 

Thank you to DMGregory for the idea.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.