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

2007-01-08 10:57 发布

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

使 用 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, 程 序 员 可 以 对 这 样 的 动 作 作 出 响 应。 缓 冲 区 中 的 项 目 是 按 时 间 标 记 的, 并 且 给 定 了 一 个 系 列 号 码, 所 以 它 们 能 够 被 正 确 地 处 理。

B Color Smilies

你可能喜欢

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