更新: 这是我写的一个处理键盘输入的库,使用 FreeBSD 许可证。我甚至已经将其标记为
v1.0
,因此我认为它已达到“发布质量”。
https://github.com/depp/keycode
我最近非常努力地为游戏制作这个东西,并且还没有完成。我将分享我所知道的。
按键码
对于游戏来说,按键码通常是你想要的。
当你在键盘上按下一个键时,操作系统首先将按钮按下转换为按键码。按键码指定了键位在键盘上的物理位置。例如,在美国键盘上,代码4可能对应于标有A的键(即使该键在法国或俄罗斯拥有不同的标签)。每个平台都有一组不同的按键码,或者可能有多个集合。你可能以其他名称来了解它们,例如扫描码或虚拟按键码。
Windows 使用虚拟按键码 (MSDN 文档)。它们在各种硬件和软件配置上都是稳定的。你可以在 <Winuser.h>
头文件中找到定义。在 Windows 上,如果你按下最左边的 home 行键(A 在美国,Q 在法国),你将得到代码65。
Mac OS X 有自 80 年代以来就一直稳定的按键码。它们在 <Carbon/Events.h>
中定义。你实际上不需要链接 Carbon 来使用按键码,但你需要这个头文件。在 OS X 上,如果你按下最左边的 home 行键,你将得到代码4。
Linux有几组不同的键码。因此,在Linux上,你有几个选择。你可以使用键符(它们有一些缺点,我将在下面解释),你可以假设用户正在使用特定的输入驱动程序(现在Evdev是一个非常好的猜测),或者你可以以某种方式找出机器使用的输入驱动程序。要获取键码,你必须读取键盘定义文件。例如,查看/usr/share/X11/xkb/keycodes/evdev
来获取Evdev键码。使用Evdev时,如果按下最左边的Home行键,你会得到代码38。
当然,如果跨平台的键码相同,那就太容易了。你可以使用特定于平台的键码或将其转换为独立于平台的值。我建议使用USB HID代码(pdf)作为独立于平台的代码,因为许多聪明的人已经经过协商并同意称呼每个键。
我上面发布的库有针对每个平台的表格,例如用于将键码转换为USB HID代码的WIN_NATIVE_TO_HID
。
艰难的部分是向用户说明他们应该按哪个按钮,但至少其他国家的人也可以玩你的游戏。
字符代码
尽管字符代码对于你和你的观众都居住在美国而言更易于使用,但你不希望使用它们。
在将按钮按下转换为键码后,操作系统会将键码转换为字符代码。字符代码受当前键盘布局的影响,并且通常还受修改键的影响。
所以,如果你在键盘上按下
A 键,在不同的平台上会得到 65、4 或 38 的键码。但是,如果 Shift 键按下,则会得到字符代码
'a'
或
'A'
;如果键盘布局设置为法语,则可能会得到
'Q'
;如果键盘布局设置为俄语,则可能会得到
'Ф'
。因此,如果你将 WASD 编码进游戏中并使用字符代码,当其他国家的人玩你的游戏时,输入将完全失效。你必须在法国使用 ZQSD,在俄罗斯使用 ЦФЫВ,很快你就会头疼。
我自己使用非 QWERTY 布局(Dvorak),大多数游戏都无法正常运行。在
W 键的位置是
,,如果你按下 Shift 键,则变成
<,有些游戏不能将其识别为相同的键。例如,我按下
, 前进,但如果我在按下 Shift 键时释放该按钮,则游戏会认为我已经释放了
< 并认为
, 仍然被按下,所以我会一直向前移动。即使我切换到美国键盘布局(我认为这是 SDL 中的一个故障),大多数使用 SDL 的游戏在 Mac 上也无法正常运行。
LibSDL
SDL 2.0 提供了平台无关的键码,称为扫描码。使用
"SDL_scancode.h"
头文件。SDL 开发人员得出了相同的结论,即扫描码应该被转换回 USB HID 码,因此 SDL 扫描码与我上面发布的库完全兼容(参见
keycode.h 和
SDL_scancode.h,数字值相同)。
出于这个原因和其他原因,如果您正在使用SDL 1.2,我强烈建议升级到2.0版。