概念页
人机接口设备
Human Interface Devices
人机接口设备 (HID) 是玩家向游戏提供输入、游戏向玩家提供反馈的硬件:手柄、键鼠、摇杆、Wii 遥控器、方向盘、跳舞毯、吉他等。GEA 从三个层面介绍它们:游戏如何与设备通信(轮询、中断、无线协议),设备提供哪几类输入,以及设备能输出哪些反馈。引擎如何加工这些原始输入见 引擎输入系统。(卷 I 9.1–9.4 节)
设备种类(卷 I 9.1)
- 主机标配手柄:Xbox Series X|S 标准手柄、PS5 的 DualSense;任天堂 Wii 以 Wii 遥控器(Wiimote)著称,Wii U 则把控制器与半移动游戏设备结合。PC 游戏通常用键鼠或手柄(微软把 Xbox 手柄设计成 Xbox 与 Windows/DirectX PC 通用)。
- 街机内置摇杆、按钮、轨迹球、方向盘等,通常按游戏定制,但同一厂商的机台常复用输入硬件。
- 主机还有专用设备与适配器:《吉他英雄》的吉他和鼓、赛车方向盘、《劲舞革命》的跳舞毯。Wiimote 常被改装用途而非被新设备取代,如《马里奥赛车 Wii》附带可插入 Wiimote 的塑料方向盘。
与 HID 通信的方式(卷 I 9.2)
| 方式 | 机制 | 例子 |
|---|---|---|
| 轮询 (polling)(9.2.1) | 周期性(通常每轮主循环一次)显式查询设备状态:直接读硬件寄存器、内存映射 I/O 端口,或通过更高层 API;输出同理写寄存器或调 API | 微软 XInput:每帧调用 XInputGetState(),得到 XINPUT_STATE,内嵌 XINPUT_GAMEPAD 结构,包含所有按钮、摇杆、扳机的当前状态(原书问题见下) |
| 中断 (interrupt)(9.2.2) | 设备只在状态变化时才发送数据(鼠标大多时间静止),通过硬件中断让 CPU 暂停主程序、运行中断服务例程 (ISR):读设备状态存起来后交还 CPU,引擎在方便时取用 | 鼠标 |
| 无线(9.2.3) | 蓝牙设备不能靠读寄存器访问,软件要用蓝牙协议「对话」:请求设备回传输入,或发送输出(震动设置、音频流)。通常由主循环之外的单独线程处理,或封装在可从主循环调用的简单接口后 | Wiimote、DualShock/DualSense、Xbox 无线手柄;对游戏程序员来说看起来与轮询设备几乎无异 |
原书问题:GEA 说
XInputGetState()「返回指向XINPUT_STATE结构的指针」。实际签名是DWORD XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState):由调用方提供结构、函数填写([out]参数),返回值是错误码(成功为ERROR_SUCCESS,未连接为ERROR_DEVICE_NOT_CONNECTED)。来源:Microsoft Learn「XInputGetState function (xinput.h)」。
中断与内核的关系见 进程、线程与纤程。
输入的类型(卷 I 9.3)
- 数字按钮(9.3.1):只有按下(down)与未按(up)两态。电路上开关有常开/常闭之分,按下对应闭合还是断开取决于硬件;软件中通常 1 位表示,常见 1 = 按下,但也可能相反(取决于电路和驱动)。所有按钮常打包成一个无符号整数:XInput 的
wButtons是 16 位WORD,位 0–3 为方向键上下左右,4 Start,5 Back,6/7 左右摇杆按下,8/9 左右肩键,12–15 为 A/B/X/Y,位 10、11 未用;用按位与掩码判断,如(pad.wButtons & XINPUT_GAMEPAD_A) != 0。 - 模拟轴与模拟按钮(9.3.2):取值为一个范围,用于扳机按下程度或摇杆二维位置(x、y 两个模拟输入),因此常被称为「轴」。有的按钮也是模拟的(能测按压力度),但信号通常噪声太大,善用的游戏很少——《合金装备 2》(PS2)瞄准模式下快速松开 X 开火、缓慢松开取消射击,适合潜行玩法。模拟输入到达引擎时已被数字化(量化为整数,有时再转成 −1 到 1 的浮点,而浮点本身也是量化的)。XInput 中摇杆为 16 位有符号整数(−32,768 左/下 到 32,767 右/上),扳机为 8 位无符号(0 未按到 255 按到底);不同主机表示不同。
- 相对轴(9.3.3):模拟按钮、扳机、摇杆是绝对的,零点明确;鼠标、滚轮、轨迹球是相对的,零表示位置未变,非零是相对上次读取的增量。
- 加速度计(9.3.4):DualShock/DualSense 与 Wiimote 内含三轴加速度计,属于相对模拟输入;不加速时为零,可测每轴最多 ±3 g,量化为三个有符号 8 位整数。
原书问题:9.3.4 说控制器「不加速时这些输入为零」,但紧接着 9.3.5 又依赖静止时测得 1 g 重力来估计朝向,两处自相矛盾。物理上加速度计测的是固有加速度 (proper acceleration):静止放在地面上的加速度计读数约为竖直向上 1 g,自由落体时才读零(Wikipedia「Accelerometer」)。因此「不加速时为零」只在扣除重力分量后才成立,9.3.5 的说法才是正确的工作原理。
- 用加速度计估计三维朝向(9.3.5):如《超级马里奥银河》中马里奥踩球,Wiimote 红外传感器朝天花板,倾斜控制球加速方向。原理是地表有恒定的 1 g(≈ 9.8 m/s²)重力加速度:水平持握、红外传感器朝向电视时 z 约为 −1 g;竖直朝天花板时 z 为 0 g、y 为 +1 g;45° 时 y、z 都约为 g。标定各轴零点后,可用反正弦、反余弦求俯仰、偏航、滚转。两个注意:手在动时加速度会混进读数使计算失效;z 轴已为重力做了标定而 x、y 没有,所以 z 轴用于测朝向的精度较低——很多 Wii 游戏要求以非标准姿势持握(按钮朝胸口或红外传感器朝天花板),让 x 或 y 轴对齐重力以提高精度(书中参考文献 [223])。
- 摄像头(9.3.6):Wiimote 独有红外传感器,本质是低分辨率摄像头;电视上方的「传感条」有两个红外 LED,在图像中成为暗背景上的两个亮点,Wiimote 内的图像处理找出亮点位置和大小(最多可检测四个),经蓝牙传给主机。两点连线的位置和方向可算出俯仰、偏航、滚转(需指向传感条),点间距可估计离电视远近,有的软件还用到点的大小。PS3 的 PlayStation Eye 是高质量彩色摄像头,可做视频会议,也可能像红外摄像头那样感知位置、朝向和深度;PS4 改进为 PlayStation Camera,配合 PlayStation Move、DualShock 4 或 DualSense 能像微软 Kinect 一样识别手势;PS5 也有高清摄像头。
输出的类型(卷 I 9.4)
| 输出 | 机制 |
|---|---|
| 震动 (rumble)(9.4.1) | DualShock 系列与 Xbox 手柄用一个或多个电机转动略微失衡的配重;游戏开关电机并控制转速,产生不同触感,模拟角色经受的颠簸或撞击 |
| 力反馈 (force-feedback)(9.4.2) | 电机驱动设备上的执行器,轻微抵抗玩家施加的运动;常见于街机赛车方向盘(模拟恶劣路况或急弯);可控制开关及力的大小与方向 |
| 触觉反馈 (haptics)(9.4.3) | PS5 DualSense 不再用失衡电机,而用 Foster Electric 定制的振动触觉执行器——线性谐振执行器 / 音圈电机,像小扬声器或 5.1/7.1 系统的低音炮,能以比直流失衡电机宽得多的频率范围重现低频信号;频率低到主要产生振动而非可闻声。触觉效果直接以音频文件制作并由执行器「播放」,开发者可逐刻精细控制手感 |
| 音频(9.4.4) | 音频通常是独立引擎系统,但 Wiimote 有小型低质扬声器;Xbox、DualShock、DualSense 有耳机口,可当 USB 音频设备做输出和麦克风输入,常用于多人游戏的 VoIP 语音 |
| 其他(9.4.5) | 世嘉 Dreamcast 的记忆卡插在手柄上;Xbox 手柄、DualShock/DualSense、Wiimote 有可由游戏点亮的 LED,DualShock/DualSense 光条颜色可控;乐器、跳舞毯等各有专属输入输出。作者认为手势界面与意念控制设备是当前最有意思的方向 |
出处
- Game_Engine_Architecture_4Ed_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 I 第 9 章 9.1–9.4 节
相关页面
游戏开发引擎输入系统Game Engine HID System多数引擎不直接使用「原始」HID 输入,而是先加工(死区、滤波)使游戏内行为平滑直观,并在 HID 与游戏之间加至少一层间接(如按键映射表把原始按钮翻译成逻辑游戏动作)。GEA 列出引擎输入系统的典型需求并逐一讲解实现:死区、模拟信号滤波、按下/松开事件、组合键与序列手势、多设备多玩家、跨平台抽象、输入重映射、上下文相关控制与输入禁用。(卷 I 9.5–9.6 节)游戏开发 · UE5增强输入Enhanced Input增强输入 (Enhanced Input) 是 UE5 默认启用的输入插件,把输入拆成四层:输入动作 (Input Action) 表示“玩家想做什么”,输入映射上下文 (Input Mapping Context) 规定“哪些按键在什么情境下触发它”,输入修饰器 (Input Modifier) 预处理原始值,输入触发器 (Input Trigger) 判定是否触发。上下文可在运行时按优先级增删,从而用数据资产而非代码处理情境切换、按键冲突与改键。游戏开发游戏循环与更新方法Game Loop & Update Method游戏循环 (Game Loop) 让游戏时间的推进与玩家输入和处理器速度脱钩:每一轮非阻塞地处理输入、更新状态、渲染,并跟踪真实时间来控制节奏;最常推荐的做法是“固定更新步长、可变渲染”。更新方法 (Update Method) 是它的搭档:世界维护一组对象,每个对象实现一个模拟“一帧”行为的 update(),每帧依次调用。两者和组件模式一起常被视为游戏引擎的核心。游戏开发进程、线程与纤程Processes, Threads & Fibers并发编程依赖操作系统提供的服务:内核态与用户态、中断、系统调用、抢占式多任务。进程只是为线程提供运行环境(虚拟地址空间与资源),线程才是操作系统的基本执行单位(调用栈 + 寄存器)。线程由内核抢占调度;纤程 (Fiber) 由程序协作调度,适合实现引擎任务系统;用户级线程与协程完全在用户空间切换上下文,更轻量。游戏数学数值表示与浮点数Numeric Representation & Floating Point游戏引擎里到处是数值,所以要清楚它们在机器中如何存储:二进制和十六进制、补码整数、定点数、IEEE-754 浮点数(量级与精度此消彼长、次正规数、机器 epsilon、ULP),以及多字节值的大小端问题和安全的类型双关 (type punning) 方法。书中一个直观的例子是:用 32 位浮点数记录以秒为单位的游戏时钟,大约 12.14 天后,加 1/30 秒就不再改变它的值。游戏策划游戏操控Game Controls"三个 C"的最后一个,也是唯一对所有游戏都适用的一个(抽象解谜、载具模拟没有角色,老式固定画面没有镜头)。Rogers 的核心原则:玩游戏的是人——手指短、运动协调一般,所以操控要讲人体工学;按下按键,动作就要发生;任何按键都不能"什么也不做";镜头相对还是角色相对,选一种坚持到底;触屏、震动与体感要语言一致、贴近现实动作(Level Up! 第 3 版 Level 7 The Three Cs, Part 3: Controls,p.171–187)。