GameInput 基础知识

大多数传统的 Microsoft 输入 API 都是以设备为中心的,这意味着应用程序代码必须首先找到它支持的输入设备 — 通常通过某种枚举模式 — 才能读取任何输入。 对于具有相对简单的输入需求的大多数游戏来说,这会增加许多额外的代码和复杂性。

另一方面,GameInput API 是以输入为中心的 API。 应用程序首先找到它们感兴趣的输入,然后可以选择查询生成这些输入的设备。 这将导致更自然的算法,而这又会导致更简单的代码。

输入流体系结构

GameInput 是在输入流概念的基础上生成的:来自连接到系统的所有设备的输入都定向到输入事件的单个连续流,并且按发生输入的顺序进行排序。 当多个设备同时生成输入时,这将导致输入事件的自然交织。 以下是来自多个输入设备的示例输入流。

来自多个输入设备的示例输入流

在此示例中,四个设备同时发送输入。 每个正方形的数目表示输入的发送顺序,颜色表示发送输入的设备。 因此,在此示例中,第一个游戏板发送第一个输入,键盘发送第二个输入,鼠标发送第三个输入,第二个游戏板发送第四个输入。

输入流中的每个元素都由“读取”表示。应用程序首先从输入流获取最新的读取。 在这里,应用程序可以或者继续定期获取最新的读取,或者可以向前和向后遍历检查相邻读取的输入流。 不管是哪一种情况,应用程序通常都会比较感兴趣的读取之间的差异,然后进行相应操作。

例如,一个第一人称射击游戏可能仅需了解在每个帧开始时是否按下了按钮,以便确定该玩家的武器是否应开火。 在此情况下,只有最新的读取有意义(并且可以忽略所有中间读取)。 另一方面,一个竞技格斗游戏可能出于以下任何原因,想要检查上一个帧和当前帧之间发生的每个输入状态变化。

  • 双击某一按钮可能会映射到与单击不同的组合/移动。
  • 两个按钮的按下顺序可能较为重要。
  • 按下两个按钮之间的时间可能较为重要。

在从输入流检索读取时,应用程序可应用可选的筛选器,以便将结果限制为来自特定输入类型(如游戏板或键盘)和/或来自特定设备的读取。 有关详细信息,请参阅 GameInput 读取

应用程序只能请求来自前半秒内发生的输入流的历史读取。 来自每个连接的设备的最新读取始终可以访问,与它有多旧无关。

接口

GameInput API 通过相关接口的集合公开,与图形和音频 API 相似,如下图所示。

通过相关接口的集合公开的 GameInput API 的示意图

有三种主要接口,它们组成大量 GameInput API 图面。

  • IGameInput 是通过调用 GameInputCreate 工厂函数获取的基础接口。 它包含多种方法,可用于从输入流检索读取、注册回调以及访问其他全局功能。

  • IGameInputReading 表示输入流中的单个元素。 它包含用于检索在读取中存储的输入状态数据的方法,以及用于访问生成了读取的设备的方法。 在向前遍历和向后遍历流的其他读取时,读取还用作输入流内的参考点。

  • IGameInputDevice 表示连接到系统的单个输入设备。 它包含用于检索设备的属性和当前状态的方法,以及用于控制设备上的触觉回馈和力回馈的方法。 它还包含用于执行低级别原始设备 I/O 的方法。

其余接口在特定的上下文中使用,这在高级 GameInput 主题部分中有所介绍。

注意

与图形和音频 API 相似,GameInput 不是真正的 COM API,即使它公开从 IUnknown 派生的接口。 这种风格的 API 有时被称为“COM lite”或“nano-COM”。虽然 IUnknown 用于引用计数和反射,但 GameInput 不使用 COM 运行时基础结构。 具体是指以下方面。

  • 应用程序既不调用 CoInitialize 也不调用 CoCreateInstance 来获取对象实例。
  • 不支持聚合之类的 COM 功能以及调用方提供的接口实现。
  • 没有跨进程封送支持,也没有单元/线程模型。 所有对象都是敏捷对象。
  • 接口指针可直接比较对象标识,而不需要经过 IUnknown。
  • 不要求方法返回 HRESULT 代码,这常常会导致更简单的函数签名。

应用程序焦点

在主机上,GameInput 仅在应用程序处于焦点时才提供对应用程序的输入。 否则,返回的状态包含中性或“静止”值,就好像用户根本没有触摸设备一样。 这消除了处理焦点变化的额外输入代码的需要。

在电脑上,默认情况下,输入将转到所有进程。 将来,此行为将可通过使用 SetFocusPolicy 方法进行更改。

当应用程序失去焦点时,将禁用要发送到设备的任何触觉或力回馈。 它仍可以调用 GameInput API 以便设置新的回馈状态,但该新状态将不会发送至设备。 当应用程序再次具有焦点时,应用程序请求的最近回馈状态将自动发送到设备。

因此,当他们获取并失去焦点时,应用程序无需执行任何与输入或触觉/力回馈相关的特殊操作。 GameInput API 始终代表自己执行正确的操作。

注意

对于某些类型的低级别设备 I/O,GameInput API 允许应用程序暂时获取对设备的独占访问权,即使它们处于后台(有关详细信息,请参阅 AcquireExclusiveRawDeviceAccess 方法)。 但是,这仅适用于输出。 除非应用程序处于焦点中,否则输入是永远无法访问的。

另请参阅

GameInput 读取

GameInput 设备

高级 GameInput 主题

GameInput API 参考