游戏入门基础]DOS到Windows的 游 戏 移 植(3) 

2007-01-08 11:29 发布

引擎学习交流 /[参考文档]
4397 0 0
 

键 盘 输 入

---- 在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 消 息。 但 是 如 果 程 序 员 直 接 管 理 键 盘, 就 算 用 户 在 其 它 应 用 程 序 中 击 键, 游 戏 还 是 会 处 理 每 一 次 击 键。 所 以 当 游 戏 失 去 输 入 焦 点 时, 一 定 要 关 闭 键 击 处 理。

B Color Smilies

你可能喜欢

游戏入门基础]DOS到Windows的 游 戏 移 植(3) 
联系
我们
快速回复 返回顶部 返回列表