转载自:https://www.cnblogs.com/saltedreed/p/12321314.html

用GLFW处理用户键盘输入有两种方式,一种是使用回调函数,一种是在每一次游戏循环中处理。这两种方法的最大差别在于是否能连续获得键盘输入,第二种方法可以。

一、回调函数

方法介绍

GLFW官方文档 对这种方法的讲解很详尽,下面只简单记录一下要点。
我们只需要自定义回调函数key_callback,并在进入游戏循环前调用函数glfwSetKeyCallback(window, key_callback)即可。下面简单介绍回调函数包含的内容。

函数头为void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods),其中,

key为按键,例如GLFW_KEY_UP,如果敲下的键不能被GLFW识别,比如Play和E-mail,key值就是GLFW_KEY_UNKNOWN;

scancode是每个平台自定义的表示按键的代码,当key值为GLFW_KEY_UNKNOWN时scancode会被用来识别键,否则scancode会被忽略;另外它可以和key一起用来获得键的名字const char* key_name = glfwGetKeyName(GLFW_KEY_W, 0);,第二个参数就是scancode。scancode可以通过const int scancode = glfwGetKeyScancode(GLFW_KEY_X);获得;

action代表动作类型,有

GLFW_PRESS:按下
GLFW_RELEASE: 松开
GLFW_REPEAT:重复按键
其中需要特别注意的是GLFW_REPEAT。引用Stack Overflow上的一个回答来解释它的意义:

Ask yourself, what is the frequency at which GLFW_REPEAT triggers? The
right answer is that this frequency depends on your user’s settings.
It is exactly the frequency at which characters will appear in any
input field in any application if you hold a character key. So the
only purpose of GLFW_REPEAT is to implement printing in your
application and make it look consistent with all other applications on
the machine. You definitely should not use GLFW_REPEAT to implement
WASD controls and other things like that.

也就是说如果我们希望在游戏中通过键盘控制一个人物的移动的话,是不能依靠GLFW_REPEAT让人物跑起来的,一个原因是移动速度不由程序员控制,容易引起游戏混乱,另一个原因是,如果像下面这样定义回调函数:

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{switch (key){// change the position of the cameracase GLFW_KEY_UP:camera_y += camera_speed;break;case GLFW_KEY_DOWN:camera_y -= camera_speed;break;...}
}

连续按“↑”键会发现摄像机位置先上移一个camera_speed的长度,卡顿一会儿,才开始连续向上移动的。当游戏人物逃避Boss追杀时,我们应该不希望他先呆住一两秒再跑吧?因此要实现连续移动的效果就需要用到第二种方法,而非通过回调函数。

mods是"modifier bits"的简写,有

GLFW_MOD_SHIFT:按下Shift键
GLFW_MOD_CONTROL:按下Ctrl键
GLFW_MOD_ALT:按下Alt键
GLFW_MOD_SUPER:无
通过key和mods的组合就可以实现诸如Ctrl+N之类的操作。

何时使用

按键速度不是特别快,不需要连续效果(比如人物不停地跑)
要处理文本输入相关事件

二、循环中处理

方法介绍

这种方法的使用方式如下:

while (!glfwWindowShouldClose(window)){processInputs(window);...}

processInputs中包含的要素和上面介绍的回调函数差不多,只是用到了另一个GLFW的函数glfwGetKey。最终效果上,这个函数返回任意时间某个键的状态,就是这个函数使得连续效果得以实现。processInputs可以这样实现:

void processInputs(GLFWwindow* window)
{// move the cameraif (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS)camera_x -= camera_speed;
}

何时使用

对按键速度要求高甚至是一直按着,需要连续效果
glfwGetKey被调用前键被松开了怎么办
除了用户的操作外,函数glfwSetInputMode也会影响到glfwGetKey的返回值。

void glfwSetInputMode(GLFWwindow* window, int mode, int value)

当mode为GLFW_STICKY_KEYS且value为GLFW_TRUE时,只要按下一个键,那么glfwGetKey返回的该键的状态一定是按下的,哪怕在glfwGetKey函数被调用前这个键又被松开了。也就是说,当我们只关心键是否被按下过、而不关心它是何时被按下的时,就可以设置这个状态。

文本输入
GLFW可以接受Unicode字符流作为输入,从而允许程序处理来自用户的文本输入。我们可以将接受的Unicode字符转换成ASCII等其他格式的字符。

在游戏循环前需要调用函数glfwSetCharCallback(window, character_callback);

回调函数的函数头为void character_callback(GLFWwindow* window, unsigned int codepoint)

分类: 计算机图形学

OpenGL学习笔记——处理键盘输入相关推荐

  1. 【OpenGL学习笔记⑧】——键盘控制正方体+光源【冯氏光照模型 光照原理 环境光照+漫反射光照+镜面光照】

    ✅ 重点参考了 LearnOpenGL CN 的内容,但大部分知识内容,小编已作改写,以方便读者理解. 文章目录 零. 成果预览图 一. 光照原理与投光物的配置 1.1 光照原理 1.2 投光物 二. ...

  2. python获取键盘输入_Python 3 学习笔记之——键盘输入和读写文件

    1. 键盘输入 Python提供了 input() 内置函数从标准输入读入一行文本,默认的标准输入是键盘.input 可以接收一个 Python 表达式作为输入,并将运算结果返回. str = inp ...

  3. Java学习笔记之键盘输入数组

    //键盘输入一组数字的方法 import java.util.Arrays; import java.util.Scanner;public class Test {public static voi ...

  4. 【OpenGL学习笔记⑦】——键盘控制镜头的平移【3D正方体 透视投影 观察矩阵 对LookAt的理解】

  5. 【OpenGL学习笔记⑥】——3D变换【旋转的正方体 实现地月系统 旋转+平移+缩放】

    ✈️ 文章目录 零. 成果预览图 一.3D立方体的顶点数组 二.纹理旋转 三.纹理缩放 四.画n个3D图形 五.轨道的数学公式 六.深度缓冲(Z 缓冲) 七.完整代码 八.参考附录: 神器的正方体 ☁ ...

  6. OpenGL 学习笔记 II:初始化 API,第一个黑窗,游戏循环和帧率,OpenGL 默认垂直同步,glfw 帧率

    前情提要: 上一篇: OpenGL 学习笔记 I:OpenGL glew glad glfw glut 的关系,OpenGL 状态机,现代操作系统的窗口管理器,OpenGL 窗口和上下文 OpenGL ...

  7. OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7888 ...

  8. C语言学习之从键盘输入任意一个字母,输出它的对应大(小)写

    C语言学习之从键盘输入任意一个字母,输出它的对应大(小)写 通过键盘随意输入一个大写或小写字母,输出它对应的小写或大写字母,若不是字母则提示"输入有误!" #include < ...

  9. OpenGL学习笔记:矩阵变换

    文章目录 缩放 glm矩阵表示 glm缩放矩阵实现 位移 齐次坐标 glm位移矩阵实现 旋转 沿x轴旋转 沿y轴旋转 沿z轴旋转 沿任意轴旋转 glm旋转矩阵实现 矩阵的组合 glm矩阵组合使用 接上 ...

最新文章

  1. 【转】centos 6.2 安装mysql-5.5.17
  2. 在最长的距离二叉树结点
  3. 文件菜单服务器属性,服务器属性(“数据库设置”页) - SQL Server | Microsoft Docs...
  4. 使用 FieldMask 提高 C# gRpc 服务性能
  5. VS2008中源文件与模块生成时的文件不同,仍要让调试器使用它吗
  6. Taro+react开发(18)--定义变量值
  7. debian java7_Debian 7 和 Debian 8 用户怎样安装 Oracle Java 8
  8. 学习算法你必须知道的一些基础知识(文末福利)
  9. 主题:ioctl函数详细说明
  10. updatebyprimarykeyselective的where条件是全部字段_多组连续数据对比,不满足单因素方差分析的条件怎么办?...
  11. win服务器自动发邮件,asp.net基于windows服务实现定时发送邮件的方法
  12. linux 网络内核 ko文件,编译内核模块 .ko文件缺少:mmzone.h bounds.h
  13. An NVIDIA kernel module ‘nvidia-drm‘ appears to already be loaded in your kernel...
  14. 【信息学奥赛一本通】题解目录答案
  15. unity学习2——基于物理模拟的太阳系模型
  16. sql server数据库宕机原因分析
  17. vos3000 检测版本失败_超级兔子安装失败检测新版本失败等问题解决方法
  18. kika平台广告sdk集成问题
  19. RocketMQ 解决 No route info of this topic 异常步骤
  20. PHP is_file 和file_exists的区别

热门文章

  1. 如何彻底删除HbuilderX
  2. 响铃:AWE2018只是“草船”,三星已成大屏电视“东风”
  3. np.zeros()生成3维
  4. Python代码实现md5加密
  5. Redis、ES、Nginx和RabbitMQ面试回忆
  6. 吐血分享:QQ群霸屏技术教程(接单篇)
  7. 程序员的自我修养 - 读书笔记文字版
  8. 实现对光网络的监控和光路切换 - MEMS 光开关
  9. Primeng PrimeFlex 的使用总结 (Angular 10)
  10. JAVA算法:解救小哈(JAVA版)