Programming 版 (精华区)

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

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

                    从DOS 到Windows 的 游 戏 移 植(7)
                                      
                                   谭 翁
                                      
     _________________________________________________________________
                                      
  使 用 DirectInput 跟 踪 鼠 标
  
   ---- 我 们 已 经 讨 论 了 一 些 在 Windows 下 读 取 鼠 标 的 常 用 方
   法。 现 在, 让 我 们 看 一 看 DirectInput 3.0 所 提 供 的 实 现 方 法
   。
   
   ---- 同 标 准 的 Windows 函 数 相 比,DirectInput 具 有 巨 大 的 速 度
   优 势。 与 DirectX 的 其 他 部 件 一 样, 它 直 接 面 向 硬 件 工 作,
   越 过 了 消 息 队 列, 甚 至 越 过 了 类 似 GetCursorPos 这 样 的 函 数
   执 行 时 所 必 须 的 数 据 操 纵。 除 此 之 外, 它 还 允 许 一 次 检
   查 所 有 的 轴 方 向 和 按 钮 的 状 态, 而 仅 需 要 一 个 简 单 的 调
   用。
   
   ---- 对 于 某 些 游 戏 的 开 发, 这 种 速 度 优 势 也 带 来 一 个 很
   大 的 缺 点。DirectInput 仅 关 心 鼠 标; 丝 毫 不 关 心 光 标, 用 它
   来 跟 踪 标 准 Windows 光 标 的 位 置 将 是 最 糟 糕 的 事 情。 所 以,
   如 果 游 戏 以 游 戏 操 纵 杆 方 式 使 用 鼠 标,DirectInput 是 很 合
   适 的, 但 是 如 果 是 鼠 标 在 屏 幕 上 引 导 着 光 标, 那 么 可 能
   还 是 要 用 GetCursorPos。
   
   ---- 注 意:DirectX 3 所 带 的 Scrawl 示 例 应 用 程 序 确 实 实 现 了
   一 个 DirectInput 驱 动 的 光 标, 虽 然 它 不 是 一 个 标 准 的
   Windows 光 标, 而 且 也 不 管 控 制 面 板 中 的 鼠 标 设 置 值。
   
   ---- 使 用 DirectInput 来 设 置 鼠 标 的 步 骤 如 下:
     * 创 建 DirectInput 对 象。 建 立 起 处 理 所 有 输 入 的 基 本 框 架
       。
     * 枚 举 设 备。 可 以 使 用 EnumDevices 来 获 得 连 接 到 系 统 的 任
       何 输 入 设 备 的 GUID ( 全 局 唯 一 标 识 符)。 如 果 只 对 标 准
       系 统 鼠 标 感 兴 趣, 可 以 跳 过 这 一 步, 因 为 DirectInput 为
       标 准 系 统 鼠 标 提 供 了 一 个 默 认 的 GUID, 可 以 在 下 一 步
       时 使 用 它。
     * 创 建 鼠 标 设 备 对 象。 为 鼠 标 创 建 一 个 代 码 对 象, 并 把
       它 连 接 到 DirectInput 对 象。
     * 设 置 合 作 级 别。 让 系 统 知 道 想 要 在 什 么 环 境 下 访 问 该
       鼠 标( 例 如, 当 应 用 程 序 在 后 台 时, 是 否 希 望 您 的 应
       用 程 序 有 访 问 能 力)。
     * 设 置 数 据 格 式。 告 诉 DirectInput 如 何 返 回 想 要 的 有 关 鼠
       标 的 信 息。
     * 捕 捉 鼠 标。 最 后, 告 诉 系 统 把 所 有 的 鼠 标 输 入 引
       入(direct) 到 应 用 程 序 窗 口。 如 果 由 于 它 被 用 于 其 他 的
       用 途 而 导 致 窗 口 丢 失 了 鼠 标, 这 一 步 必 须 重 复 进 行。
       
   ---- 下 面 的 Moby Dick 的Windows 版 中 的 INPUT.CPP 模 块 演 示 了 以
   上 初 始 化 过 程。 这 里 所 使 用 的 语 法 是 C++ 的, 但 是
   DirectInput 可 以 使 用 普 通 的 C。

extern HINSTANCE             hTheInstance; // 程 序 实 例
extern HWND                  hMainWindow;  // 应 用 程 序 窗 口 句 柄
extern BOOL                  MouseAcquired;// 我 们 自 己 的 标 志
static LPDIRECTINPUT         lpdi;         // DirectInput 接 口
static LPDIRECTINPUTDEVICE   lpdiMouse;    // 鼠 标 设 备 接 口

BOOL InitInput(void)
  {
  if(DirectInputCreate(hTheInstance, DIRECTINPUT_VERSION, &lpdi, NULL)
     != DI_OK)
  return FALSE;

// 我 们 将 跳 过 枚 举 的 步 骤, 因 为 我 们 只 关 心 标 准 系 统 鼠 标。
if(lpdi->CreateDevice(GUID_SysMouse, &lpdiMouse, NULL)
     !=DI_OK)
    return FALSE;

  if(lpdiMouse->SetCooperativeLevel(hMainWindow,
         DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK)
  return FALSE;

  // 注 意:c_dfDIMouse 是 一 个 外 部 DIDATAFORMAT 结 构,
 是 由 DirectInput 提 供 的。
  if (lpdiMouse->;SetDataFormat(&c_dfDIMouse) != DI_OK)
      return FALSE;
  if (lpdiMouse->Acquire() != DI_OK)
      return FALSE;
  MouseAcquired = TRUE;
  return TRUE;
  }  // InitInput()

   ---- DirectInput 非 常 友 好, 它 提 供SetDataFormat 的 默 认 数 据 格
   式, 这 样 程 序 员 就 无 须 为 设 置 它 而 浪 费 很 多 精 力。
   
   ---- 下 面 的 代 码 片 段 检 查 鼠 标 的 当 前 位 置, 并 且 当 左 边
   按 钮 被 按 下 时 就 执 行 某 些 操 作。 注 意 MouseXY 是 跟 踪 鼠 标
   的 绝 对 位 置, 而 diMouseState 保 持 着 相 对 坐 标。

POINT        MouseXY;
BOOL         MouseAcquired;
DIMOUSESTATE diMouseState;

if (MouseAcquired)
  {
  if (lpdiMouse->GetDeviceState(sizeof(diMouseState), &diMouseState)
       == DI_OK)
    {
    MouseXY.x += diMouseState.lX;
    MouseXY.y += diMouseState.lY;
    if (diMouseState.rgbButtons[0]) DoSomething();
    }
  }

   ---- 注 意:GetDeviceState 并 不 报 告 光 标 相 对 于 屏 幕 或 窗 口 的
   位 置; 它 报 告 鼠 标 的 移 动 轨 迹( 以 "mickeys" 为 单 位, 一 个
   mickey 是 能 够 被 记 录 到 的 最 小 的 鼠 标 移 动 单 位)。 换 句 话
   说, 如 果 光 标 已 经 移 动 到 屏 幕 的 边 缘, 但 是 用 户 还 是 向
   同 一 方 向 推 动 鼠 标, 则 GetDeviceState 所 报 告 的 像 素 值 是 不
   断 变 化 的。 如 果 用 户 打 开 了 鼠 标 加 速 功 能, 则 移 动
   Windows 光 标 一 个 给 定 的 距 离 可 能 会 产 生 或 多 或 少 的
   mickeys, 这 取 决 于 加 速 如 何 作 用。
   
   ---- 默 认 情 况 下,GetDeviceState 返 回 相 对 于 其 最 后 一 次 被 调
   用 位 置 的 相 对 鼠 标 位 置。 可 以 使 用 SetProperty 来 改 变 这 种
   状 况, 使 返 回 值 是 绝 对 位 置 值, 但 是 这 些 值 实 际 上 只 是
   所 有 相 对 移 动 的 总 和, 并 且 应 用 程 序 可 以 非 常 容 易 地 完
   成 这 种 计 算, 如 上 面 的 示 例 所 示。 如 果 真 的 想 要 使 用
   SetProperty, 那 么 它 必 须 恰 好 在 查 询 鼠 标 之 前、 而 在 所 有
   其 他 的 设 置 都 已 经 完 成 之 后 完 成。
   
   ---- 另 外 还 有 一 个 函 数 与 鼠 标 有 关GetDeviceData, 它 不 是 检
   查 硬 件 的 当 前 状 态, 而 是 从 由 DirectInput 保 持 的 缓 冲 区 中
   读 取。 对 于 某 些 按 键 和 微 小 动 作, 由 于 其 后 紧 接 着 一 个
   抵 消 动 作( 例 如, 按 键 动 作 后 面 紧 跟 一 个 松 开 键 的 动 作)
   , 从 而 导 致 游 戏 循 环 没 有 机 会 检 测 鼠 标 的 状 态, 则 该 动
   作 非 常 容 易 丢 失。 通 过 使 用 GetDeviceData 而 不 是
   GetDeviceState, 程 序 员 可 以 对 这 样 的 动 作 作 出 响 应。 缓 冲
   区 中 的 项 目 是 按 时 间 标 记 的, 并 且 给 定 了 一 个 系 列 号 码
   , 所 以 它 们 能 够 被 正 确 地 处 理。
   
     _________________________________________________________________
                                      

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