人气 172

[游戏程序] 游戏入门基础]DOS到Windows的 游 戏 移 植(7) [复制链接]

九艺网 2017-3-10 17:01:20

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x

使 用 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。

  1.                         extern HINSTANCE             hTheInstance; // 程 序 实 例



  2. extern HWND                  hMainWindow;  // 应 用 程 序 窗 口 句 柄



  3. extern BOOL                  MouseAcquired;// 我 们 自 己 的 标 志



  4. static LPDIRECTINPUT         lpdi;         // DirectInput 接 口



  5. static LPDIRECTINPUTDEVICE   lpdiMouse;    // 鼠 标 设 备 接 口







  6. BOOL InitInput(void)



  7.   {



  8.   if(DirectInputCreate(hTheInstance, DIRECTINPUT_VERSION, &lpdi, NULL)



  9.      != DI_OK)



  10.   return FALSE;



  11.   



  12. // 我 们 将 跳 过 枚 举 的 步 骤, 因 为 我 们 只 关 心 标 准 系 统 鼠 标。



  13. if(lpdi->CreateDevice(GUID_SysMouse, &lpdiMouse, NULL)



  14.      !=DI_OK)



  15.     return FALSE;







  16.   if(lpdiMouse->SetCooperativeLevel(hMainWindow,



  17.          DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK)



  18.   return FALSE;



  19.   



  20.   // 注 意:c_dfDIMouse 是 一 个 外 部 DIDATAFORMAT 结 构,



  21. 是 由 DirectInput 提 供 的。



  22.   if (lpdiMouse->;SetDataFormat(&c_dfDIMouse) != DI_OK)



  23.       return FALSE;



  24.   if (lpdiMouse->Acquire() != DI_OK)



  25.       return FALSE;



  26.   MouseAcquired = TRUE;



  27.   return TRUE;   



  28.   }  // InitInput()



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

  1.                         POINT        MouseXY;



  2. BOOL         MouseAcquired;



  3. DIMOUSESTATE diMouseState;







  4. if (MouseAcquired)



  5.   {



  6.   if (lpdiMouse->GetDeviceState(sizeof(diMouseState), &diMouseState)



  7.        == DI_OK)



  8.     {



  9.     MouseXY.x += diMouseState.lX;



  10.     MouseXY.y += diMouseState.lY;



  11.     if (diMouseState.rgbButtons[0]) DoSomething();



  12.     }



  13.   }



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

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

QQ|手机版|小黑屋|九艺游戏动画论坛 ( 津ICP备2022000452号-1 )

GMT+8, 2024-4-17 05:40 , Processed in 0.066844 second(s), 23 queries .

Powered by Discuz! X3.4  © 2001-2017 Discuz Team.