Mac OS X 游戏如何接收低级键盘输入事件?
游戏需要对键盘输入进行低级访问。在 Windows 上,有 DirectInput。但 Mac OS X 游戏开发人员使用什么技术呢?
显然,有足够多的 Mac 游戏可以正确地进行键盘输入,而没有常见解决方案的缺点:
解决方案#1:使用 keyUp / keyDown 事件
-(void)keyUp:(NSEvent*)event;
-(void)keyDown:(NSEvent*)event;
不可接受的缺点: keyDown 事件重复基于“按键重复率”和“按键重复延迟”的系统首选项设置。这会导致初始 keyDown 事件,然后暂停,然后开始以系统首选项设置定义的速率重复。该方案不能用于连续按键事件。
我想知道是否可以禁用按键重复行为?我想您可以读取第一个 keyDown 键,然后记住类中的“带有 keyCode x 的键按下”状态,直到收到该键的 keyUp 事件,从而绕过重复延迟和重复率问题。
解决方案#2:使用 Quarts 事件点击
请参阅 Quartz 事件服务参考。这似乎是足够低水平的。
不可接受的缺点:需要在通用访问 - 键盘下的系统偏好设置中启用辅助设备。虽然默认情况下此功能可能处于打开状态,但不能保证它在某些系统上可能会被关闭。
我还读到 Quartz 事件点击需要应用程序以 root 身份运行,但没有找到对此的确认。
解决方案#3:Carbon 事件/IOKit HID
Carbon 事件管理器参考 已标记作为遗留物,不应用于新的开发。
不可接受的缺点:没有人知道未来的 Mac OS 版本将继续支持 Carbon 事件多久。
除了 Carbon 是一个遗留框架之外,这似乎仍然是最好的解决方案。但是使用 Carbon Events 还有其他缺点吗?
问题:
Mac OS X 游戏开发人员使用哪些技术来接收低级键盘输入事件?如果他们使用上述技术之一,他们如何解决我提到的缺点?
更新:
我最终转向使用常规 NSEvent 消息并将它们包装在 用于轮询键盘状态的简洁 API。
Games need low-level access to keyboard input. On Windows, there's DirectInput. But what technology do Mac OS X game developers use?
Obviously, there's enough Mac games which get keyboard input just right, without the drawbacks of the commonly known solutions:
Solution #1: Use keyUp / keyDown events
-(void)keyUp:(NSEvent*)event;
-(void)keyDown:(NSEvent*)event;
Inacceptable drawback: keyDown events are repeated based on the system preference settings for "key repeat rate" and "key repeat delay". This causes an initial keyDown event followed by a pause before it starts repeating at a rate defined by a system preference setting. This solution can not be used for continuous key events.
I wonder if the key repeat behavior can be disabled? I suppose that you could read the first keyDown key, then remember the "key with keyCode x is down" state in your class until the keyUp event is received for that key, thus bypassing the repeat delay and repeat rate issues.
Solution #2: Use Quarts Event Taps
See Quartz Event Services Reference. It seems to be sufficiently low-level.
Inacceptable drawback: requires Assistive Devices to be enabled in system preferences under Universal Access - Keyboard. While this may be on by default, there is no guarantee that it might be turned off on some systems.
I also read that Quartz event taps require the app to run as root, but found no confirmation for this.
Solution #3: Carbon Events / IOKit HID
The Carbon Event Manager Reference is marked as legacy and should not be used for new development.
Inacceptable Drawback: no one knows how long the Carbon events will continue to be supported in future Mac OS versions.
Apart from Carbon being a legacy framework, this still seems to be the best solution. But are there any other drawbacks for using Carbon Events?
Questions:
Which technology do Mac OS X game developers use for receiving low-level keyboard input events? If they use one of the above technologies, how do they work around the drawbacks I mentioned?
UPDATE:
I eventually turned to using the regular NSEvent messages and wrapped them in a neat API for polling the keyboard states.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我在#3方面运气不错,但如果你想支持键盘之外的任何东西,它需要做很多繁重的工作。
不过,在我们深入探讨之前,先简单说明一下,Carbon 和 IOKit HID 是两个独立的东西。碳可能会在某个时候消失。但 IOKit HID 将会继续存在,并在 10.5 中进行了一次漂亮的改版。
有关这些内容如何组合在一起的完整示例,请查看 https://github。 com/OpenEmu/OpenEmu/blob/master/OpenEmu/OEHIDManager.m。这只是拼图的一小部分,因为其中还有其他文件。
您想要执行的操作的文档可以在 http: //developer.apple.com/library/mac/#documentation/DeviceDrivers/Conceptual/HID/new_api_10_5/tn2187.html
同样,这不会很快消失,并且与碳和碳事件完全分开。
I have had good luck with #3, but it requires a lot of heavy lifting if you want to support anything beyond the keyboard.
One quick point before we dive in though, Carbon and IOKit HID are two separate thing. Carbon may go away at some point. But IOKit HID is here to stay and just got a nice facelift in 10.5.
For a full example of how this stuff all fits together, take a look at https://github.com/OpenEmu/OpenEmu/blob/master/OpenEmu/OEHIDManager.m. That is a small piece of the puzzle as there are other files in there as well.
The documentation for what you're wanting to do can be found http://developer.apple.com/library/mac/#documentation/DeviceDrivers/Conceptual/HID/new_api_10_5/tn2187.html
Again, this is not going to disappear anytime soon and is completely separate from Carbon and Carbon Events.
我参加这个聚会迟到了,但这是我使用 Swift 编写的 OSX 游戏的解决方案。这非常简单,而且看起来效果很好。
首先,您可以将此代码放入正在接收键盘事件的控制器中:
然后,系统的其他部分可以确定是否按下了特定的键:
或者循环遍历当前按下的所有键
注意:keysDown 是一个 Swift Set,因此您可以不必担心重复或排序。密钥要么在集合中,要么不在集合中。
我不太确定键码的标准化程度如何。但是您可以提供一个键盘配置页面,用户可以在其中为每个操作键入按键,然后保存发生的任何键码。
I'm late to this party, but here's my solution for an OSX game I'm writing using Swift. It's very simple, and seems to be working pretty well.
First you can put this code in the controller which is receiving keyboard events:
Then, other parts of the system can determine if a particular key is down:
Or loop through all the keys which are currently pressed
Note keysDown is a Swift Set, so you don't have to worry about duplicates or ordering. A key is either in the set or it isn't.
I'm not too sure how standardised the keycodes are. But you could offer a keyboard configuration page where the user can type keys for each action, and then save whatever keycode this happened to be.
好吧,我参加聚会确实迟到了,但我认为我的解决方案是开门见山的,类似于上面霍华德先生的解决方案。请记住,此输入用于控制 SpriteKit 游戏中的相机。这样您就可以获得平稳的连续运动和精确的停止。
Ok so I'm really late to the party but I think mine is just straight to the point and resembles Mr. Howards solution above. Keep in mind this input is being used to control the camera in a SpriteKit game. This way you get smooth continuous movement and precise stopping.
看看 ControllerMate 和 Manymouse。
http://icculus.org/manymouse/
http://www.orderedbytes.com/controllermate/
Have a look at ControllerMate and manymouse.
http://icculus.org/manymouse/
http://www.orderedbytes.com/controllermate/
polkit(Obj-C 工具包)中还有一些设备类,包括...
http://code.google.com/p/polkit/
There are also some Device Classes in polkit (Obj-C toolkit) including ...
http://code.google.com/p/polkit/
我发现了一个使用 Quartz Event Taps 的很好的例子。
但问题是:
对于某些事件类型,用户需要以 root 权限运行应用程序。例如,拦截 keydown 和 keyup 事件需要 root。
拦截是系统范围的,这意味着当程序运行时,它将捕获所有关键事件,甚至是发送到其他应用程序的事件。实施时需要非常小心,以免破坏其他应用程序。
I found a very good example of using Quartz Event Taps.
however the problems are:
for certain event types, the user needs to run the application in root privilege. for example intercepting keydown and keyup events requires root.
the interception is system wide, which means when the program runs, it will capture all key events even those sent to other applications. implementation needs to be very careful in order to not to break other applications.