Programming 版 (精华区)
发信人: superman (☆风雨无阻☆), 信区: Programming
标 题: [转载] DOS到Windows的 游 戏 移 植(3)
发信站: 紫 丁 香 (Sat Aug 29 07:35:42 1998), 站内信件
【 以下文字转载自 cnprogram 讨论区 】
【 原文由 Young_Yang@bbs.ustc.edu.cn 所发表 】
从DOS 到Windows 的 游 戏 移 植(3)
谭 翁
_________________________________________________________________
键 盘 输 入
---- 在DOS 和Windows 两 个 版 本 的 Moby Dick 中, 我 们 都 保 持 了 一
个 键 状 态 表, 当 有 对 Move_Ahab 的 调 用 时, 该 表 能 够 告 诉 我
们 按 下 的 是 哪 一 个 光 标 键 或 数 字 键 盘 键。 但 是 在 Windows
版 中 我 们 不 能 使 用 键 盘 中 断 处 理 程 序 来 更 新 该 表---- 那
些 代 码 是 在 黑 箱 内 部 的, 不 允 许 我 们 打 开。
---- 为 此,Windows 给 我 们 提 供 了 两 种 跟 踪 键 盘 状 态 的 方
法---- 通 过 按 下 或 松 开 一 个 键 时 产 生 的 消 息, 或 通 过 函 数
调 用 来 检 查 键 盘 状 态。 让 我 们 来 看 看 如 何 用 这 两 种 方 法
在 Moby Dick 中 更 新 键 表。
响 应 消 息
---- 处 理 键 盘 输 入 的 最 明 显 的 方 法, 与 在 Moby Dick 的 DOS 版
的 中 断 处 理 程 序 中 所 使 用 的 方 法 类 似。 借 助 于 Windows 消
息 系 统 的 帮 助, 我 们 查 看 所 有 有 关 方 向 键 的 按 下 和 松 开
, 并 做 出 响 应, 立 即 更 新 键 表。 当 然, 这 项 工 作 是 在
WM_KEYDOWN 和 WM_KEYUP 消 息 的 响 应 函 数 中 完 成 的---- 如 果 程 序
员 是 个“Windows 好 市 民” 的 话。
---- 这 种 方 法 的 问 题 是, 当 快 速 地 轻 敲 一 个 键, 那 么 这 个
键 的 状 态 也 许 会 在 被 Move_Ahab 查 询 之 前 便 已 返 回 到“ 未 按
下” 状 态 了; 换 句 话 说, 这 次 击 键 丢 失 了。 这 在 任 何 的 应
用 程 序 中 都 是 不 允 许 的, 在 游 戏 中, 有 可 能 玩 家 想 要 通
过 轻 敲 一 个 键 给 出 一 个 游 戏 动 作。
---- 一 种 解 决 方 法 是 在 程 序 中 保 持 键 的“ 按 下” 状 态 一 直
到 我 们 真 正 响 应 该 键 击。 只 当 接 收 到 WM_KEYDOWN 消 息 时 才
不 断 更 新 该 键 表, 而 不 处 理 WM_KEYUP 消 息。 而 在 Move_Moby 函
数 重 用 GetAsyncKeyState 来 检 查 各 键 当 前 是 否 是 按 下 的。 如
果 不 是, 在 表 中 清 除 该 键 的 项 目。
---- 虽 然 在 Moby Dick 中 我 们 不 是 这 样 做 的, 但 是 下 面 的 程
序 片 段 显 示 了 如 何 实 现 它:
---- LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM
wParam, LPARAM lParam)
....
case WM_KEYDOWN:
switch( wParam )
{
case VK_LEFT:
key_table[INDEX_LEFT] = 1;
break;
// 对 于 其 它 键 同 样 处 理
...
break;
....
} // WindowProc 结 束
int Move_Ahab();
{
...
if (key_table[INDEX_LEFT])
{
AhabX--
if (!GetAsyncKeyState(VK_LEFT)) key_table[INDEX_LEFT] = 0;
}
// 对 于 键 表 的 其 余 部 分 同 样 处 理
...
} // end of Move_Ahab
检 查 键 盘 状 态
---- 但 是 实 际 上, 在 Moby Dick Windows 中 我 们 的 做 法 是: 如 果
我 们 想 要 使 用( 几 乎) 直 接 访 问 硬 件 的 GetAsyncKeyState, 我
们 同 时 越 过 消 息 系 统。
---- GetAsyncKeyState 有 一 个 方 便 之 处 是 它 的 返 回 值 中 包 含
两 项 信 息。 返 回 值 最 高 位 告 诉 我 们 该 键 现 在 是 否 是 按 下
的。 当 我 们 检 查 键 盘 时, 这 非 常 有 用, 但 是 在 这 之 间 的 时
间 段 怎 么 样, 即 我 们 如 何 保 持 快 速 的 键 击 不 被 丢 失 ? 那
就 是 返 回 的 信 息 中 另 一 项 的 作 用。 如 果 该 键 从 上 一 次 我
们 查 询 时 到 现 在 曾 经 被 按 下 过-- 就 算 它 现 在 未 被 按 下,
最 低 位 也 将 被 置 位。 所 以, 只 要 简 单 地 看 一 下
GetAsyncKeyState 的 非 零 的 返 回 值, 我 们 就 可 以 知 道 该 键 是
否 被 按 下, 或 者 自 它 上 次 被 调 用 后 是 否 被 按 下 过。( 当 然
, 我 们 不 能 说 出 该 键 从 上 一 次 检 查 到 现 在 是 否 被 按 下 了
两 次, 但 是 游 戏 循 环 检 查 键 盘 的 速 度 足 够 快, 可 以 保 证
这 个 问 题 不 会 发 生。)
---- 在 API 参 考 中, 有 一 个 关 于 GetAsyncKeyState 的 重 要 事 情
没 有 被 详 细 的 解 释。 返 回 值 的 最 低 位 仅 由 一 个“ 正 式 的”
键 击 置 位-- 就 是 说, 只 有 在 考 虑 了 重 复 延 迟 和 重 复 速 率
的 用 户 设 置 值 之 后, 一 个 键 才 被 认 为 是 按 下 的。 如 果 您
在 编 写 一 个 字 处 理 应 用 程 序, 当 然 不 希 望 出 现“
ttthhhiiisss ” 这 样 的 情 况, 那 么 就 要 检 查 这 一 位。 很 显 然
, 在 实 时 键 盘 处 理 中 我 们 不 能 仅 仅 依 靠 最 低 位 一 条; 如
果 我 们 这 样 做 的 话,Ahab 在 响 应 一 个 保 持 按 下 的 键 时 将 会
犹 犹 豫 豫 移 动 一 个 方 格, 然 后 以“ 控 制 面 板” 中 规 定 的 速
率 沿 一 个 方 向 继 续 前 进。 很 幸 运 的 时, 最 高 位 反 映 了 该
键 的 当 前 的、 未 经“ 翻 译” 的 状 态, 并 且 我 们 使 用 它 来 控
制 连 续 的 按 键。
---- 注 意: 当 应 用 程 序 处 于 后 台 时, 它 将 仍 然 保 持 工 作。
如 果 程 序 员 按 照“ 好 市 民” 的 方 式 跟 踪 键 盘, 那 么 就 无 须
为 此 担 心 什 么, 因 为 它 不 会 接 收 到 任 何 WM_KEYDOWN 或
WM_KEYUP 消 息。 但 是 如 果 程 序 员 直 接 管 理 键 盘, 就 算 用 户
在 其 它 应 用 程 序 中 击 键, 游 戏 还 是 会 处 理 每 一 次 击 键。
所 以 当 游 戏 失 去 输 入 焦 点 时, 一 定 要 关 闭 键 击 处 理。
_________________________________________________________________
--
※ 来源: 中国科大BBS站 [bbs.ustc.edu.cn]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: poster.hit.edu.c]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.729毫秒