TIMESTEPS and DELTA TIME
本节实现引擎中的 TimeStep 系统
Hazel 中 TimeStep 实现的原理主要是计算并记录当前帧和上一帧之间经历的时长,然后通过这个间隔来控制我们将照相机或者物体移动时候的速度。虽然不同机器执行一次Loop函数的用时不同,但只要把每一帧里的运动,跟该帧所经历的时间相乘,就能抵消因为帧率导致的数据不一致的问题。
为什么要这么做?
试想对于不同的设备,据两个最简单的例子,有两台 30fps 和 60fps 的电脑,也就是说,第一台电脑每 33ms 更新一帧,第二台每 16.7ms更新一帧,但是我们设置相机移动的时候,是在每次调用 OnUpdate 函数的时候,给原本的位置或者角度添加一个偏移量,如此一来,对于不同帧率的电脑,按下相同时间的按键,那么 60fps 的电脑上面物体会运动更远的距离!这是我们不希望看到的,因此要设置 Delta Time 来控制,假定每帧运动 1 个单位,对于 30fps ,1s 可以运动30,60fps 可以运动 60,可以看到 60fps 比 30fps 快了一倍,原因就是 60fps 更新一帧所用的时间(TimeStep)比 30fps 少一倍,为了解决这个问题,可以给运动的速度乘上对应的 TimeStep,这样 1s 中运动的距离就统一了。
实际的操作就是给 OnUpdate 函数添加一个参数 TimeStep,首先新建 Core 文件夹创建 TimeStep.h
添加 TimeStep 类:
class TimeStep
{
public:
TimeStep(float time = 0.0f)
: m_Time(time)
{}
operator float() const { return m_Time; }
float GetSeconds() const { return m_Time; }
float GetMilliseconds() const { return m_Time * 1000.f; }
private:
float m_Time;
};
之后在 runloop 中更新:
float time = (float)glfwGetTime(); //Platform GetTime()
TimeStep timeStep(time - m_LastFrameTime);
m_LastFrameTime = time;
for (Layer* layer : m_LayerStack)
layer->OnUpdate(timeStep);
SandBox:
void OnUpdate(Hazel::TimeStep ts) override
{
HZ_TRACE("Delta time: {0}s ({1}ms)", ts.GetSeconds(), ts.GetMilliseconds());
if (Hazel::Input::IsKeyPressed(HZ_KEY_LEFT))
m_CameraPosition.x -= m_CameraMoveSpeed * ts;
else if (Hazel::Input::IsKeyPressed(HZ_KEY_RIGHT))
m_CameraPosition.x += m_CameraMoveSpeed * ts;
if (Hazel::Input::IsKeyPressed(HZ_KEY_DOWN))
m_CameraPosition.y -= m_CameraMoveSpeed * ts;
else if (Hazel::Input::IsKeyPressed(HZ_KEY_UP))
m_CameraPosition.y += m_CameraMoveSpeed * ts;
if (Hazel::Input::IsKeyPressed(HZ_KEY_Q))
m_CameraRotation += m_CameraRotationSpeed * ts;
else if (Hazel::Input::IsKeyPressed(HZ_KEY_E))
m_CameraRotation -= m_CameraRotationSpeed * ts;