Programming 版 (精华区)
发信人: superman (☆风雨无阻☆), 信区: Programming
标 题: [转载] DOS到Windows的 游 戏 移 植(8)
发信站: 紫 丁 香 (Sat Aug 29 07:35:56 1998), 站内信件
【 以下文字转载自 cnprogram 讨论区 】
【 原文由 Young_Yang@bbs.ustc.edu.cn 所发表 】
从DOS 到Windows 的 游 戏 移 植(8)
谭 翁
_________________________________________________________________
---- 在 本 系 列 文 章 的 前 面 几 部 分 中, 我 们 介 绍 了 一 个 简
单 的DOS 游 戏Moby Dick, 并 且 带 它 走 过 了 在 Win32 环 境 下 开 发
的 第 一 阶 段。 现 在, 我 们 将 对 该 游 戏 的 Windows 版 添 加 更 多
的 功 能: 立 体 声 效 果、MIDI 音 乐、TrueType 字 体、 和
用DirectDraw 图 形 实 现 的 透 明 效 果 的“ 捣 蛋 鬼”。
---- Moby Dick 只 是 为 Windows 95 编 写 的, 不 是 为 Windows NT。 同
时 因 为 该 游 戏 的 图 形 程 序 使 用 了 DirectDraw , 所 以 必 须 在
系 统 中 安 装 DirectX。
---- 所 提 供 的 可 执 行 文 件 使 用 了 DirectSound。 要 编 译 一 个
不 支 持DirectSound 的 版 本, 注 释 掉 文 件 MOBY.CPP 中 的 "#define
USE_DIRECTSOUND" 一 行 即 可。 提 供 这 个 选 项 是 为 了 能 够 比 较
使 用 DirectSound 方 法 和 使 用 Windows 中 传 统 方 式 播 放 声 音 的
差 异。 这 里 对 主 游 戏 循 环 做 了 一 些 很 小 却 非 常 重 要 的 修
改。 在 以 前 的 文 章 中, 我 们 讲 述 了 在 实 时 游 戏 中 使 用
PeekMessage 好 处。 然 而,PeekMessage 循 环 会 大 量 消 耗 CPU 时 间,
即 使 该 应 用 程 序 是 处 于 后 台 并 且 理 论 上 没 有 做 任 何 事 情
。 所 以, 当 Moby Dick 被 放 在 后 台 暂 停 执 行 时, 我 们 添 加 了
一 个 对 WaitMessage 的 调 用。 该 函 数 悬 挂 该 线 程, 直 到 在 队
列 中 出 现 一 个 消 息。
本 文 讨 论 声 音 的 处 理
从.VOC 到.WAV 的 转 变
---- 有 多 种 免 费 软 件 和 共 享 实 用 程 序 可 以 将8 位 .VOC 文 件
转 换 为 .WAV 文 件; 可 以 查 阅 CompuServe 上 的 Windows AV 论 坛
(WINAV) 或 在 ftp://x2ftp.oulu.fi/pub/msdos/programming 站 点 上 的 大
量 与 编 程 有 关 的 文 章。 在 购 买 声 卡 时 也 可 能 得 到 了 这 样
的 实 用 程 序, 例 如 购 买 Sound Blaster 会 随 卡 奉 送 VOC2WAV.EXE。
使 用 PlaySound 播 放 声 音
---- 将.WAV 文 件 编 译 到 可 执 行 程 序 中 并 播 放 的 步 骤 如 下:
---- 1. 从 一 个 .WAV 文 件 直 接 播 放 声 音。 要 使 Moby 有 声 音 的
“ 喷 气”, 仅 需 写 一 行 代 码: PlaySound("blow.wav", NULL,
SND_ASYNC | SND_FILENAME);
---- 其 参 数 是: (1) 文 件 名; (2) 包 含 该 资 源 的 程 序 模 块 句
柄, 我 们 用NULL 表 示 没 有 把 他 编 译 进 程 序 的 资 源 中, 因 为
我 们 没 有 使 用 一 个 已 编 译 的 资 源; (3) 标 志, 确 保 该 函 数
能 够 尽 可 能 快 的 返 回, 而 不 是 等 待 声 音 播 放 结 束, 并 且
指 明 第 一 个 参 数 是 文 件 名。 要 把 该 声 音 文 件 作 为 一 个 资
源 编 译 到 可 执 行 文 件 中, 需 要 在 资 源 (.RC) 文 件 中 添 加 下
面 一 行:
---- IDR_WAVE_BLOW WAVE "blow.wav"
---- IDR_WAVE_BLOW 是 在 头 文 件 RESOURCE.H 中 定 义 的 一 个ID。
WAVE 是 应 用 程 序 中 定 义( 主 观 命 名 的) 的 资 源 类 型。 声 音
与 图 标 和 位 图 不 同, 不 是 标 准 资 源, 所 以 必 须 分 配 一 个
类 型 名。
---- 当 需 要 从 资 源 中 播 放 声 音 时, 下 面 的 这 行 代 码 完 成
这 个 工 作:
PlaySound(MAKEINTRESOURCE(IDR_WAVE_BLOW), hTheInstance,
SND_ASYNC | SND_RESOURCE);
---- 在 这 里, 第 一 个 参 数 是 资 源 名( 由 宏 MAKEINTRESOURCE 将
数 字 标 识 符 转 换 而 来)。 第 二 个 参 数 是 包 含 资 源 的 程 序
模 块 句 柄( 在 Moby 的 例 子 中 , 就 是 主 程 序 句 柄)。 最 后 面
的 标 志 已 经 被 改 变, 以 指 示 第 一 个 参 数 是 资 源 名 而 不 是
文 件 名。
使 用 DirectSound 播 放 声 音
---- 在 游 戏 中 的 不 同 时 间 点 播 放 简 单 的 声 音, 使 用
PlaySound 就 足 够 了, 但 是 这 种 方 法 不 允 许 运 行 中 混 频 或 其
他 效 果。Windows API 的 多 媒 体 扩 展 中 有 一 组 函 数, 它 们 的 名
称 大 多 以 WAVE 开 头, 允 许 更 高 级 的 调 整, 但 是 这 些 都 被
DirectX Software Development Kit (SDK) 的 一 个 部 件 DirectSound 所 取
代。DirectSound 3 有 许 多 高 级 的 功 能, 包 括 自 动 混 频、3D 声 音
( 在 双 声 道 系 统 模 拟“ 环 绕 音 响”) 和 立 体 声, 使 用 它 可
以 带 来 很 大 好 处。 DirectSound 不 提 供 幕 后 加 载 和 解 释 能 力
, 而 这 些 功 能 PlaySound 都 提 供。 解 释 .WAV 文 件 是 程 序 员 的
责 任, 并 且 要 把 数 据 复 制 到 第 二 缓 冲 区( 第 二 缓 冲 区 在
后 台 保 持 数 据, 当 播 放 声 音 时, 这 些 数 据“ 流 入” 第 一 缓
冲 区。 程 序 员 无 须 考 虑 第 一 缓 冲 区 的 问 题, 它 由
DirectSound 保 持。) 示 例 工 程 在 文 件 WAVE.CPP 中 完 成 声 音 的
加 载 和 解 释, 声 音 数 据 是 从 一 个 资 源 加 载 的。 这 段 代 码
很 长, 所 以 在 这 里 就 不 引 述 它。 有 关 直 接 读 取 .WAV 文 件 的
简 单 代 码, 请 您 参 阅 有 关 文 章。
---- 一 旦 建 立 起 DirectSound 的 第 二 缓 冲 区, 事 情 就 又 变 得
简 单 了。 要 播 放 声 音, 只 需 调 用 DIRECTSOUNDBUFFER 对 象 的
Play 方 法 即 可:
---- lpDSB_Blow- > Play(0, 0, 0);
---- 在 当 前 版 本 的 DirectSound 中, 头 两 个 参 数 总 是 为 0 。 如
果 要 重 复 播 放 声 音, 可 以 把 第 三 个 参 数 设 置 为
DSBPLAY_LOOPING。
---- Moby Dick Windows 版 演 示 了 循 环 声 音, 以 及 当 两 个 .WAV 文
件 竞 争 时, 使 用 PlaySound 和 DirectSound 的 Play 方 法 的 不 同 结
果。 在 Settings 菜 单 中 打 开 声 音, 并 且 单 击 左 键 开 始
"boing" 声 音( 这 是 Queequeg 的 鱼 叉 的 声 音, 它 在 bungee 绳 索
上)。 使 用 右 键 停 止 声 音。 如 果 编 译 该 程 序 时 预 定 义 了
USE_DIRECTSOUND( 或 者 使 用 所 提 供 的 可 执 行 程 序),"boing" 和
Moby 的 沉 重 呼 吸 声 被 DirectSound 混 在 一 起 同 时 播 放。 如 果
没 有 定 义 USE_DIRECTSOUND,Moby 在 循 环 声 音 时 将 保 持 安 静, 因
为 PlaySound 在 同 一 时 间 只 能 做 一 件 事 情。
---- 下 面 您 介 绍 一 下 如 何 实 现 一 个 简 单 的 立 体 声 效 果。
假 设 有 一 个 立 体 声 的 声 卡, 在Moby 的 DirectSound 版 中, 鲸 鱼
的 有 声 的 吹 气 的 移 动 步 伐, 依 赖 于 气 流 的 方 向 是 朝 向 游
戏 屏 幕 的 右 边 还 是 左 边。Moby 每 呼 吸 一 次, 程 序 只 是 简 单
地 以 -10,000 到 10,000 的 为 度 量 计 算 其 相 对 的 东 西 位 置。 然
后 将 这 个 整 数 值 传 递 给 缓 冲 区 的 SetPan 方 法:
---- lpDSB_Blow- > SetPan(pan);
---- 这 一 操 作 在 Play 被 调 用 之 前 完 成。DirectSound 依 据 pan 的
从 0 开 始 的 划 分, 自 动 按 比 例 地 减 弱 一 个 声 道 或 另 一 个
声 道 的 回 放 声 音。 当 第 一 个 声 道 被 减 弱 时, 另 一 个 声 道
保 持 全 高 的 声 音。 换 句 话 说, 当 Moby Dick 位 于 其 世 界 的 死
角 时, 两 个 声 道 都 是 全 高 的 声 音; 当 它 走 到 最 东 或 最 西
边 时, 有 一 个 声 道 是 没 有 声 音 的。
播 放 MIDI 文 件
---- Windows 通 过 多 媒 体 API 提 供 了 对 回 放 MIDI 文 件 的 高 级
和 低 级 支 持。 高 级 支 持 是 以 媒 体 控 制 接 口 (MCI) 函 数 的 形
式 提 供 的。 这 种 情 况 下, 使 用 MIDI 格 式 0 和 1 可 以 工 作, 但
是 MIDI 格 式 2 不 能 工 作。
---- MCI 函 数 实 际 上 可 以 有 两 种 不 同 的 调 用 方 法
。mciSendString 函 数 使 用 看 起 来 不 象 计 算 机 代 码 的 字 符 串
命 令 来 控 制 MIDI 序 列 器(sequencer)( 或 其 他 任 何 的 媒 体 播 放
器)。 下 面 的 例 子 打 开 一 个 序 列 器, 并 且 读 要 回 放 的 文 件
:
mciSendString(
"open song.mid type sequencer alias aria",
lpszReturnString, lstrlen(lpszReturnString), NULL);
---- 该 调 用 定 义 了 文 件 名、 设 备 类 型 以 及 别 名( 在 示 例 中
是 "aria"), 它 可 用 于 后 续 的 调 用 中, 这 些 后 续 的 调 用 可
以 播 放、 暂 停 或 以 其 他 的 方 法 控 制 数 据 回 放。
---- 下 面 是mciSendCommand 的 列 出 顺 序:
MCI_OPEN_PARMS mciOpenParms;
MCI_PLAY_PARMS mciPlayParms;
DWORD dwReturn;
mciOpenParms.lpstrDeviceType = "sequencer";
mciOpenParms.lpstrElementName = "song.mid";
dwReturn = mciSendCommand(NULL, MCI_OPEN,
MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)(LPVOID) &mciOpenParms));
---- 在 MOBY.CPP 中, 读 者 可 以 看 到 mciSendCommand 的 一 个 简 单
实 现。 该 程 序 从 开 始 到 结 束 简 单 地 播 放 一 个 音 调, 同 时
Windows 操 作 系 统 发 送 一 条 消 息 到 该 应 用 程 序。 程 序 对 该
消 息 的 响 应 就 是 再 次 播 放 该 声 音。
---- 在 文 件 CGMIDI.CPP 中 演 示 了 一 个 播 放 MIDI 文 件 的 低 级 实
现 方 法, 这 个 程 序 在 DirectX SDK 的 "Immortal Klowns" 示 例 的 源
文 件 中 可 以 找 到。 这 个 示 例 没 有 使 用 MCI, 而 是 把 音 乐 文
件 加 载 到 内 存 中, 然 后 使 用 Windows MIDI 流 设 备 把 数 据“ 流
” 到 MIDI 序 列 器 中,Windows MIDI 流 设 备 没 有 自 定 义 编 译 序
列 代 码 的 效 率 高, 但 是 比 MCI 的 效 率 高。 如 果 不 想 要 程 序
在 运 行 时 访 问 硬 盘 驱 动 器, 甚 至 访 问 CD-ROM, 预 先 加 载 数
据 是 一 个 好 方 法。
---- 在DOS 下, 使 用“ 流” 到 序 列 器 的 方 法 可 能 能 够 抢 救 大
多 数 现 存 代 码( 在 Windows 下 实 现 时 钟 时 允 许 不 同)。 但 是
, 我 们 提 倡 使 用 CGMIDI.CPP 中 的 程 序, 无 论 是 否 修 改 它。
_________________________________________________________________
--
※ 来源: 中国科大BBS站 [bbs.ustc.edu.cn]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: poster.hit.edu.c]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:207.702毫秒