使用 SDL2 和 OpenGL 没有 instantaneous/jerky 移动
Non instantaneous/jerky movement using SDL2 & OpenGL
我一直在研究一个小型 3D 引擎,试图修复相机并使其不那么抖动。我一直在使用 SDL 进行输入,当它工作时,它正在做这件事,如果我按住一个按钮,它会立即移动一次,然后暂停,然后开始正确移动,使移动感觉反应迟钝。
我录制了它的 GIF,虽然可能有点难以看出发生了什么,但愿它能提供一些想法:
向前然后向右移动就像:
w wwwwwwwwwwwwwwwwaaaaaaaaaaaaaaaaaaaaa
这里有重要的代码,但如有必要,请随时索取更多代码:
//Poll events
SDL_Event event;
while (m_EngineState != EngineState::EXIT)
{
m_last = m_current;
m_current = SDL_GetPerformanceCounter();
deltaTime = (double)((m_current - m_last) * 1000 / SDL_GetPerformanceFrequency());
while (SDL_PollEvent(&event))
{
switch (event.type) {
case SDL_QUIT:
m_EngineState = EngineState::EXIT;
break;
case SDL_MOUSEMOTION:
break;
case SDL_KEYDOWN:
m_Keys[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
m_Keys[event.key.keysym.sym] = false;
break;
}
ProcessEvents();
}
void Engine::ProcessEvents()
{
if (m_Keys[SDLK_w])
{
m_Camera->MoveForward(5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_s])
{
m_Camera->MoveForward(-5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_d])
{
m_Camera->MoveRight(5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_a])
{
m_Camera->MoveRight(-5.0f*(deltaTime*0.001));
}
}
void Camera::MoveForward(float amount)
{
m_pos += m_forward * amount;
}
void Camera::MoveRight(float amount)
{
m_pos += glm::cross(m_forward, m_up) * amount;
}
不要将 SDL_PollEvent
与 SDL_KEYDOWN
和 SDL_KEYUP
事件一起使用,它受限于 OS 键盘重复率。这非常适合打字,但不适合 camera/player 控件。请改用 SDL_GetKeyboardState(NULL) 来查询键的当前状态。
例如:
Uint8* keystate = SDL_GetKeyboardState(NULL);
if (keystate[SDL_SCANCODE_W])
{
m_Camera->MoveForward(5.0f*(deltaTime*0.001));
}
if (keystate[SDL_SCANCODE_S])
{
m_Camera->MoveForward(-5.0f*(deltaTime*0.001));
}
我一直在研究一个小型 3D 引擎,试图修复相机并使其不那么抖动。我一直在使用 SDL 进行输入,当它工作时,它正在做这件事,如果我按住一个按钮,它会立即移动一次,然后暂停,然后开始正确移动,使移动感觉反应迟钝。
我录制了它的 GIF,虽然可能有点难以看出发生了什么,但愿它能提供一些想法:
向前然后向右移动就像:
w wwwwwwwwwwwwwwwwaaaaaaaaaaaaaaaaaaaaa
这里有重要的代码,但如有必要,请随时索取更多代码:
//Poll events
SDL_Event event;
while (m_EngineState != EngineState::EXIT)
{
m_last = m_current;
m_current = SDL_GetPerformanceCounter();
deltaTime = (double)((m_current - m_last) * 1000 / SDL_GetPerformanceFrequency());
while (SDL_PollEvent(&event))
{
switch (event.type) {
case SDL_QUIT:
m_EngineState = EngineState::EXIT;
break;
case SDL_MOUSEMOTION:
break;
case SDL_KEYDOWN:
m_Keys[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
m_Keys[event.key.keysym.sym] = false;
break;
}
ProcessEvents();
}
void Engine::ProcessEvents()
{
if (m_Keys[SDLK_w])
{
m_Camera->MoveForward(5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_s])
{
m_Camera->MoveForward(-5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_d])
{
m_Camera->MoveRight(5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_a])
{
m_Camera->MoveRight(-5.0f*(deltaTime*0.001));
}
}
void Camera::MoveForward(float amount)
{
m_pos += m_forward * amount;
}
void Camera::MoveRight(float amount)
{
m_pos += glm::cross(m_forward, m_up) * amount;
}
不要将 SDL_PollEvent
与 SDL_KEYDOWN
和 SDL_KEYUP
事件一起使用,它受限于 OS 键盘重复率。这非常适合打字,但不适合 camera/player 控件。请改用 SDL_GetKeyboardState(NULL) 来查询键的当前状态。
例如:
Uint8* keystate = SDL_GetKeyboardState(NULL);
if (keystate[SDL_SCANCODE_W])
{
m_Camera->MoveForward(5.0f*(deltaTime*0.001));
}
if (keystate[SDL_SCANCODE_S])
{
m_Camera->MoveForward(-5.0f*(deltaTime*0.001));
}