Programming 版 (精华区)

发信人: superman (☆风雨无阻☆), 信区: Programming
标  题: [转载] DOS到Windows的 游 戏 移 植(5)
发信站: 紫 丁 香 (Sat Aug 29 07:35:48 1998), 站内信件

【 以下文字转载自 cnprogram 讨论区 】
【 原文由 Young_Yang@bbs.ustc.edu.cn 所发表 】

                    从DOS 到Windows 的 游 戏 移 植(5)
                                      
                                   谭 翁
                                      
     _________________________________________________________________
                                      
  Moby Dick 修 订 版
  
   ---- 在 本 系 列 文 章 的 前 面 几 篇 中, 笔 者 介 绍 了 一 个 名
   为Moby Dick 的 简 单 的DOS 游 戏, 并 且 讨 论 将 其 移 植 到32
   位Windows 环 境 下。 现 在, 我 们 要 把 游 戏 操 纵 杆 和 鼠 标 输 入
   程 序 加 入 到 该 游 戏 的 两 个 版 本 中。 键 盘 输 入 程 序 仍 旧 保
   持 不 变。 本 文 讨 论 前 半 部 分: 游 戏 操 纵 杆 的 实 现。
   
   ---- Moby Dick 的DOS 版 本 中 大 部 分 是 普 通 的C。 在 Turbo C++ 3.0
   下,DOS 版 不 需 要 修 改 就 可 以 编 译 通 过。 如 果 没 有 使 用
   Turbo 工 程 文 件, 一 定 要 关 掉 寄 存 器 变 量。Windows 版 是
   Visual C++ 4.0 的 一 个 工 程, 但 是 它 也 适 应 其 它 编 译 器。 对
   于 DirectInput 的 方 法(Methods), 它 使 用 了 C++ 的 调 用, 而 其 它
   情 况 下 都 是 不 使 用 类 的。
   
   ---- 如 果 计 算 机 连 接 着 游 戏 操 纵 杆,Moby Dick 的 Windows 版 会
   自 动 允 许 使 用 它, 除 非 在 Settings 菜 单 中 设 置 为 使 用 鼠 标
   移 动。 实 际 上Windows 有 两 个 不 同 的 鼠 标 接 口, 要 看 编 译 期
   间 是 否 定 义 了 USE_DIRECTINPUT。( 本 篇 文 章 所 提 供 的 编 译 版
   本 没 有 使 用 DirectInput; 如 果 希 望 添 加 该 定 义 后 编 译 代 码
   , 则 需 要 有 DirectX 2 或 者 DirectX 3 SDK)。 在 第 一 个 接 口 变
   量 中, 使 用 了 标 准 的 Windows 函 数 GetCursorPos,Ahab( 船 长) 总
   是 移 向 光 标。 在 DirectInput 版 本 中, 船 长 则 根 据 鼠 标 的 移
   动 而 移 动, 并 不 考 虑 光 标 的 位 置。
   
  DirectInput
  
   ---- 过 去 游 戏 开 发 者 都 尽 量 避 开 Windows, 因 为 他 们 已 经 习
   惯 于 DOS 环 境 下 的 执 行 和 控 制, 而 这 些 Windows 是 拒 绝 提 供
   的。 动 画 一 直 是 最 大 的 工 作 障 碍, 有 人 认 为 可 以 用
   DirectDraw 和 Direct3D 有 效 地 解 决 这 一 问 题, 然 而 这 种 解 决
   方 案 又 带 来 了 其 它 的 问 题, 其 中 之 一 就 是 输 入 问 题。
   
   ---- 在 今 天 的 实 时 游 戏 中, 帧 的 速 率 一 直 增 加, 要 求 快 速
   地 反 应 玩 家 的 动 作。DirectInput 试 图 满 足 这 一 直 接 读 取 键
   盘、 鼠 标 和 游 戏 操 纵 杆 的 需 求, 它 的 做 法 是 在 保 持 了 基
   于 Windows 应 用 程 序 的 设 备 无 关 特 性 的 前 提 下, 让 应 用 程
   序 在 尽 可 能 低 的 级 别 上 读 取 这 些 设 备。
   
   ---- DirectX 3 SDK 是 第 一 个 包 含 DirectInput 的 DirectX 版 本, 它
   是 在 1996 年 9 月 发 行 的。DirectInput 实 际 上 不 是 DirectX 2 SDK
   的 组 成 部 分, 同 样 也 不 是 它 的 前 辈--Windows 95 Game SDK 的 组
   成 部 分。 在 那 些 版 本 中,DirectInput 只 是 由 在 标 准 Windows 应
   用 程 序 编 程 接 口(API) 中 的 游 戏 操 纵 杆 服 务 组 成, 除 此 之
   外 还 包 括 控 制 面 板 中 的 设 置 功 能 及 可 用 于 允 许 支 持 数 字
   游 戏 操 纵 杆 的 驱 动 模 式。DirectX 3 扩 展 了 DirectInput 的 范 围
   , 使 它 包 含 了 有 关 鼠 标 和 键 盘 的 基 于 COM 的 API。
   
   ---- 顺 便 说 一 下,DirectInput 提 供 的 新 的 键 盘 服 务 具 有 一 些
   优 点, 要 优 于 在 Moby Dick Windows 的 第 一 个 版 本 中 曾 使 用 过
   的 GetAsyncKeyState。 新 的 功 能 包 括 读 取 所 有 的 键, 而 不 仅 仅
   是 那 些 具 有 实 际 键 码 的 键, 并 且 能 够 为 多 线 程 设 置 事 件
   对 象(event objects)。 但 是 目 前,Moby Dick Windows 仍 将 使 用
   GetAsyncKeyState, 因 为 它 在 实 时 读 取 键 盘 时 还 是 令 人 满 意
   的。
   
  对 游 戏 操 纵 杆 编 程
  
   ---- 在 DirectInput 中, 术 语“ 游 戏 操 纵 杆”(joystick) 也 同 样
   包 含 游 戏 把 手(game pads)、 飞 行 操 纵 杆(flight yokes) 和 踏
   板 系 统(pedal system) 以 及 类 似 的 设 备, 本 文 使 用 这 一 术 语
   时, 同 样 包 含 这 些 设 备。
   
   ---- 读 取 游 戏 操 纵 杆 既 可 以 通 过 Windows 消 息, 也 可 以 通 过
   轮 询。 对 于 前 者, 窗 口 可 以 用 joySetCapture 来 捕 获 游 戏 操 纵
   杆, 当 游 戏 操 纵 杆 移 动 或 按 钮 按 下 时, 就 会 通 知 窗 口。 这
   样 就 可 能 把 游 戏 操 纵 杆 变 成 象 鼠 标 那 样 的 指 示 设 备: 每
   次 操 纵 杆 的 角 度 发 生 变 化 时, 用 户 就 可 以 在 屏 幕 上 移 动
   指 针。 然 而,Moby Dick 更 关 心 每 次 经 过 游 戏 循 环 时 游 戏 操
   纵 杆 的 位 置, 而 不 是 游 戏 操 纵 杆 的 实 际 移 动, 所 以 需 要
   使 用 joyGetPosEx 进 行 轮 询, 而 不 是 监 视 消 息 队 列。
   
   ---- 不 使 用 joySetCapture 的 另 外 一 个 原 因 是 操 纵 杆 的 信 息
   受 到 了 很 大 的 限 制, 仅 支 持 三 个 轴 方 向( 例 如, 左- 右、
   前- 后 和 阀 门(throttle)) 和 四 个 按 钮。 像Microsoft Sidewinder
   3D Pro 这 样 的 现 代 输 入 设 备 有 8 个 按 钮、 一 个 point-of-view
   hat 和 四 个 轴 方 向 的 移 动( 包 括 一 个 阀 门 滑 块 和 一 个 在 操
   纵 杆 上 的 拧 转(twisting) 移 动), 这 显 然 是 无 法 满 足 要 求
   的。 对 于 最 新 的 游 戏 操 纵 杆 和 游 戏 把 手, 则 需 要
   joyGetPosEx 的 威 力, 它 具 有 返 回 32 个 按 钮、6 个 轴 方 向 以 及
   POV hat 的 能 力, 除 此 之 外 还 完 全 支 持 数 字 和 模 拟 设 备。
   
   ---- API 参 考 建 议 使 用 过 去 的 游 戏 操 纵 杆 设 备 函 数
   joyGetPos, 只 能 有 三 个 轴 方 向 和 四 个 按 钮。 确 实,JoyGetPos
   实 现 起 来 非 常 简 单, 但 是 joyGetPosEx 可 以 与 所 有 的 游 戏 操
   纵 杆 一 起 工 作, 功 能 更 强。
   
   ---- 要 在 程 序 中 包 含 扩 展 的 游 戏 操 纵 杆 服 务, 需 要 链 接
   WINMM.LIB , 且 要 包 含 MMSYSTEM.H。
   
  检 测 游 戏 操 纵 杆
  
   ---- 要 检 测 游 戏 操 纵 杆, 只 要 使 用 JOYSTICKID1 作 为 参 数 调
   用 joyGetPosEx 即 可:

JOYINFOEX joyInfoEx;
ZeroMemory(joyInfoEx, sizeof(joyInfoEx);
joyInfoEx.dwSize = sizeof(joyInfoEx);
BOOL JoyPresent = (joyGetPosEx
(JOYSTICKID1, &joyInfoEx) == JOYERR_NOERROR);

   ---- 如 果 游 戏 操 纵 杆 没 有 被 正 确 地 安 装 在 Windows 中, 或 者
   没 有 被 插 在 计 算 机 上, 函 数 将 返 回 一 个 错 误( 非 零)。
   
   ---- 注 意: 就 像 许 多 其 它 的 DirectX 函 数 一 样, 必 须 让
   joyGetPosEx 知 道 它 需 要 填 补 的 结 构 有 多 大, 这 会 使 人 感 到
   烦 恼, 但 对 于 软 件 的 向 上 兼 容 是 必 需 的。
   
   ---- 游 戏 软 件 开 发 者 不 需 要 游 戏 操 纵 杆 配 置 校 准 的 功 能
   , 因 为 这 是 用 户 的 责 任, 用 户 可 以 在 控 制 面 板 下 选 择 游
   戏 操 纵 杆 和 配 置 校 准。 如 果 开 发 者 想 在 游 戏 菜 单 里 给 用
   户 提 供 这 样 一 个 机 会, 只 要 调 用 控 制 面 板 的applet 即 可:
   
   ---- WinExec("control joy.cpl", SW_NORMAL);
   
  “ 死 区”(Dead Zone)
  
   ---- 在 Moby Dick MS-DOS 中, 笔 者 为 了 在 X 轴 和 Y 轴 中 心 的 周
   围 创 建 一 个“ 死 区”, 而 做 了 一 些 计 算。 如 果 没 有 这 个 区
   域 的 话, 要 把 船 沿 一 个 轴 方 向 移 动 几 乎 是 不 可 能 的。 因
   为 游 戏 操 纵 杆 在 向 另 一 个 轴 方 向 上 稍 有 偏 差 就 会 导 致 船
   斜 行。
   
   ---- joyGetPosEx 的JOY_USEDEADZONE 标 志 扩 展 了 游 戏 操 纵 杆 的 不
   明 确 位 置 的 范 围, 并 且 称 这 一 范 围 为 死 区。 游 戏 操 纵 杆
   驱 动 程 序 将 对 在 这 一 死 区 中 的 所 有 位 置 返 回 一 个 常 数 值
   。
   
   ---- 创 建 死 区 须 注 意 以 下 要 点:
     * 必 须 在 注 册 表( 在 REGSTR.H 中 定 义 的 键 下) 中 设 置 死 区
       界 限, 并 且 通 过 调 用 joyConfigChanged 来 通 知 系 统。
     * 计 算 死 区 所 返 回 的 常 数 值。 其 可 行 的 一 种 方 法 是 将 死
       区 的 范 围 设 置 成 与 整 个 游 戏 操 纵 杆 的 控 制 范 围 大 小
       相 同, 读 取 轴 的 位 置, 然 后 将 死 区 重 新 设 置 成 实 际 想
       要 设 置 的 大 小。
     * 关 掉 程 序 时, 应 确 保 恢 复 注 册 表 的 原 始 值, 因 为 其 它
       应 用 程 序 可 能 希 望 它 是 默 认 值。
       
   ---- 在 Moby Dick Windows 中 的 计 算 方 法 与 在 MS-DOS 版 本 中 一 样
   。
   
  使 用Throttle
  
   ---- 笔 者 在 Moby Dick Windows 中 给Ahab 的 船 上 添 加 了 一 个
   throttle, 这 一 方 面 是 为 了 更 有 趣, 另 一 方 面 可 以 显 示 读
   取 游 戏 操 纵 杆 的 控 制 是 非 常 简 单 的, 它 和 任 何 一 个 有 第
   三 轴 方 向 或Z 轴( 除 X 轴 和 Y 轴 之 外) 的 设 备 一 起 工 作。 一
   般 第 三 个 方 向 的 轴 是 通 过 装 在 底 部 上 的 滑 块 或 轮 子 来 控
   制 的。
   
   ---- 获 得 throttle 信 息 的 方 法 如 下:
JOYCAPS   joyCaps;
JOYINFOEX joyInfoEx;
ZeroMemory(joyInfoEx, sizeof(joyInfoEx);

// 看 一 个 throttle 是 否 可 用
joyGetDevCaps(JOYSTICKID1, &joyCaps, sizeof(joyCaps));
BOOL JoyHasThrottle = (joyCaps.wCaps & JOYCAPS_HASZ);

// 如 果 可 用, 读 其 位 置
if (JoyHasThrottle)
{
  joyInfoEx.dwSize = sizeof(joyInfoEx);
  joyInfoEx.dwFlags = JOY_RETURNZ;
  joyGetPosEx(JOYSTICKID1, &joyInfoEx);
}

   ---- joyInfoEx.dwZpos 提 供 的 就 是 throttle 的 位 置, 可 以 从
   joyCaps 的 wZmin 和 wZmax 区 域 中 计 算 出 它 的 相 对 位 置。
   
   ---- 另 外, 可 以 通 过 将JOY_RETURNZ 与 其 它 标 志 相 结 合( 使 用
   “or” 操 作 符), 从 而 只 用 一 个 单 独 的 调 用 就 可 获 得 操 纵
   杆 的 位 置、 按 钮 状 态 等 信 息。
   
   ---- 除 了 X、Y 和 Z 轴 以 外, 还 有 其 它 三 个 轴 可 以 进 行 监 控
   :R( 用 于 舵(Rudder))、U 和 V。 这 些 方 向 适 用 于 脚 踏 板、 旋
   转 游 戏 操 纵 杆 和 其 它 各 种 不 同 的 滑 块、 旋 钮、 和 标 度 盘,
   但 不 包 括 POV hat, 它 的 位 置 返 回 在 JOYINFOEX 结 构 的 dwPOV 区
   域 中。
   
     _________________________________________________________________
                                      

--
※ 来源: 中国科大BBS站 [bbs.ustc.edu.cn]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: poster.hit.edu.c]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:211.690毫秒