【问题标题】:No, really. What is the proper way to handle keyboard input in a game using Cocoa?不完全是。在使用 Cocoa 的游戏中处理键盘输入的正确方法是什么?
【发布时间】:2011-08-16 05:42:37
【问题描述】:

假设您正在为 Mac OS X 创建游戏。事实上,假设您正在创建 Quake,但它是 2011 年,您更愿意只使用现代的、未弃用的框架。

您希望在用户按下(或释放)键盘上的键(任意键)时通知您的游戏。这包括修改键,如 shift 和 control。 编辑添加:另外,您想知道修改键的左或右版本是否被按下。

您还希望您的游戏有一个配置屏幕,用户可以在其中检查和修改键盘配置。它应该包含以下内容:

  • 前进:W
  • 跳跃:空间
  • 火:LCTRL

你是做什么的?一天左右以来,我一直试图找到一个好的答案,但没有成功。

这是我想出的:

  • 子类 NSResponder,实现 keyUp: 和 keyDown:,就像在 this answer 中一样。这种方法的一个问题是,当用户仅按下修饰键时,不会调用 keyUp: 和 keyDown:。要解决这个问题,您可以实现 flagsChanged:,但这感觉像是 hack。
  • 使用Quartz Event Tap。这仅适用于应用程序以 root 身份运行,或者用户启用了对辅助设备的访问权限。此外,修饰键事件仍然不算作常规键事件。
  • 使用 HI 工具箱。在 10.6 开发者文档中几乎没有提及它。它似乎非常非常不推荐使用。

那么,这样做的正确方法是什么?这真的感觉像是一个应该有一个众所周知的、有据可查的解决方案的问题。游戏并不是非常小众。

【问题讨论】:

  • FWIW,我不认为 -flagsChanged:NSFlagsChangedMask 是黑客。这是记录在修改键(如 Control)更改时通知的方式。
  • 我并不是说 flagsChanged: 是一种 hack,而是说使用它为此目的感觉就像是一种 hack。如果您正在编写文本编辑器,那么以不同的方式处理修饰键事件是个好主意!但是,如果您想知道刚刚按下了哪个键,无论可能是哪种键,flagsChanged: 似乎都不适合我。当然,您可以存储 [event modifierFlags] 的值并对此进行比较——它可以做到——但我觉得应该有一个更好、更直接的方法,这已经足够了。有吗?
  • 我认为没有其他方法。据我所知,Cocoa 遵循您所描述的推理:在大多数情况下,修饰键本身并不相关。也就是说,您可以将-keyDown:-keyUp:-flagsChanged: 抽象为一两个有效地执行应用程序中的操作的方法——这三个方法将简单地过滤事件并调用您的自定义方法。
  • 呸,奇怪的行为。我已经通过使用静态计数器解决了这个问题:在您的 if 部分,我增加了计数器,如果计数器小于 2,则认为它是一个键;否则,我会减少计数器并将其视为向上键。在else 部分,我递减计数器并将其视为向上键。我只为一个键做到了这一点;您必须为每个修饰键设置一个计数器。
  • 我不确定这是一个好的解决方案,因为 2 是恒定的,我猜理论上用户有可能拥有多个键盘,而 2 应该是 4。我无法对此进行测试,不过。

标签: cocoa macos


【解决方案1】:

正如其他人所说,使用-flagsChanged: 没有任何问题。还有另一种选择:使用 IOKit HID API。无论如何,您都应该将其用于操纵杆/游戏手柄输入,并且可以说是鼠标输入;键盘输入可能也可能不方便,具体取决于您在做什么。

【讨论】:

  • 好吧,就像我在问题的 cmets 中提到的那样,使用 flagsChanged: is 有问题:为此,它似乎没有将左侧和右修饰键。 (不过,这个要求不在我最初的问题中。我的错。) IOKit HID API 看起来很有希望。我会调查的!
  • 是的,这是赢家。我有点难以理解 API,但根据我迄今为止能够破解的内容,这提供了我需要的东西。干杯!
  • 将 HID 用于键事件的一个复杂问题是将键映射到配置界面的字符和符号。方便的是,我为此编写了一个库。我已经很多年没有测试过了,但最后我听说它有效。 jens.ayton.se/code/keynaming
【解决方案2】:

这看起来很有希望:

+[ NSEvent addLocalMonitorForEventsMatchingMask:handler: ]

似乎是 10.6 中的新内容,听起来就像您正在寻找的一样。更多内容:

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/Reference/Reference.html%23//apple_ref/occ/clm/NSEvent/addLocalMonitorForEventsMatchingMask:handler:

【讨论】:

  • 不,这仍然不会将修饰键事件视为常规键事件(观察 NSKeyDownMask 和 NSFlagsChangedMask)。它似乎只是一种像 NSResponder 一样获得事件通知的方法,而无需创建实例。
  • 这基本上是问题中提到的Quartz事件点击的Cocoa版本。
猜你喜欢
  • 1970-01-01
  • 2021-01-07
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多