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毫秒