Ner*_*ond 3 c++ keyboard input glfw
我正在尝试使用 glfwSetKeyCallback 函数创建基本的相机运动。问题是它不处理一次输入多个键,比如 W 和 A 应该将它对角左上角方向移动。相反,它就像只知道最后输入的密钥。所以假设我按 A 向左移动,它向左移动,然后我按 W 向左上角移动,相反它“忘记”了 A 被按下并向上移动。
float cameraSpeed = 0.02f;
if (key == GLFW_KEY_ESCAPE && (action == GLFW_PRESS || action == GLFW_REPEAT))
glfwSetWindowShouldClose(window, GLFW_TRUE);
if (key == GLFW_KEY_W && (action == GLFW_PRESS || action == GLFW_REPEAT))
Game::GetInstance()->cameraY += cameraSpeed;
if (key == GLFW_KEY_A && (action == GLFW_PRESS || action == GLFW_REPEAT))
Game::GetInstance()->cameraX -= cameraSpeed;
if (key == GLFW_KEY_S && (action == GLFW_PRESS || action == GLFW_REPEAT))
Game::GetInstance()->cameraY -= cameraSpeed;
if (key == GLFW_KEY_D && (action == GLFW_PRESS || action == GLFW_REPEAT))
Game::GetInstance()->cameraX += cameraSpeed;
Run Code Online (Sandbox Code Playgroud)
我想到的一个解决方案是创建我自己的键盘输入布尔选项卡,并仅使用 GLFW 函数来设置它们,例如:
if (key == GLFW_KEY_A && action == GLFW_PRESS)
// set 'A' to true;
if (key == GLFW_KEY_A && action == GLFW_RELEASE)
// set 'A' to false;
Run Code Online (Sandbox Code Playgroud)
然后在完全独立的函数/类/任何东西中用它做我想做的事。不过在我看来它并不干净。什么是解决问题的好方法?
我遇到了同样的问题,并决定使用回调来设置关键状态的数组。GLFW_REPEAT仅在最后按下的键时发送。我的回调直接委托给一个Input类,但这无关紧要:它们传递了所有参数。
void key_callback(GLFWwindow *win, int key, int scancode, int action, int mods){
Input *input = (Input*)glfwGetWindowUserPointer(win);
input->keys(win, key, scancode, action, mods);
}
Run Code Online (Sandbox Code Playgroud)
Input 中定义的按键数组:
bool pressed[KEYS]; // KEYS = 349 (last GLFW macro, GLFW_KEY_MENU = 348)
Run Code Online (Sandbox Code Playgroud)
以及实际的处理方法,其中我还处理需要窗口指针的特殊键:
Input::keys(GLFWwindow *win, int key, int scancode, int action, int mods){
if(key == GLFW_UNKNOWN) return; // Don't accept unknown keys
if(action == GLFW_PRESS)
pressed[key] = true;
else if(action == GLFW_RELEASE)
pressed[key] = false;
switch(key){
case GLFW_KEY_EXCAPE:
if(action == GLFW_PRESS)
glfwSetWindowShouldClose(win, true);
}
}
Run Code Online (Sandbox Code Playgroud)
然后我在每次渲染操作后处理主循环内的每个键Input::handle(void),使用如下Input in(); in.handle():
void Input::handle(void){ // Things to do every frame
for(int i = 0; i < KEYS; i++){
if(!pressed[i]) continue; // Skip if not pressed
switch(i){
case GLFW_KEY_SPACE:
cam->ascend(1.0); // Ascend with camera
}
}
}
Run Code Online (Sandbox Code Playgroud)
我计划包含一个时间常数来处理不同帧速率的问题,但这就是它的要点。
结果:即使按下多个键,相机也能向各个方向平滑移动。