第 3 章 打 地 鼠 本 章 将 创 建 一 个 打 地 鼠 的 游 戏, 游 戏 灵 感 来 自 一 款 经 典 的 街 机 游 戏 Whac-A-Mole, 其 中 的 小 动 物 会 突 然 从 洞 中 冒 出, 玩 家 则 用 木 槌 击 打 它 们, 击 中 得 分 打 地 鼠 的 创 作 者 是 一 名 App Inventor 团 队 的 成 员, 与 其 说 她 是 为 了 测 试 sprite 组 件 的 功 能 ( 她 做 到 了 ), 不 如 说 是 她 自 己 喜 欢 玩 游 戏 当 Ellen Spertus 加 入 Google 公 司 的 App Inventor 团 队 时, 她 希 望 App Inventor 也 可 以 用 于 游 戏 的 开 发, 因 此 她 自 告 奋 勇 地 承 担 起 sprites 的 实 现 任 务 sprite 原 本 用 来 表 示 神 话 中 的 角 色, 如 仙 女 妖 精 等, 到 20 世 纪 70 年 代 开 始 出 现 在 计 算 机 界, 用 来 代 表 那 些 能 够 在 电 脑 屏 幕 上 移 动 的 图 像 ( 在 电 子 游 戏 中 ) Ellen 第 一 次 使 用 sprite 是 在 20 世 纪 80 年 代 早 期, 她 曾 经 参 加 电 脑 训 练 营 并 使 用 TI 99/4 编 程 她 在 sprites 以 及 打 地 鼠 游 戏 上 所 做 的 努 力, 受 到 了 双 重 怀 旧 情 绪 的 驱 使 计 算 机 以 及 游 戏 她 童 年 时 代 的 最 爱
可 以 查 看 Android 版 打 地 鼠 游 戏 的 视 频 教 程 此 教 程 由 Wolber 教 授 基 于 上 一 个 版 本 的 App Inventor 录 制 的, 但 同 样 可 以 有 助 于 理 解 开 发 过 程 图 3-1 打 地 鼠 游 戏 的 用 户 界 面 学 习 目 标 如 图 3-1 所 示 的 打 地 鼠 应 用 将 实 现 以 下 功 能 : 一 只 地 鼠 随 机 出 现 在 屏 幕 上, 每 秒 钟 移 动 一 次 ; 如 果 手 指 触 碰 到 地 鼠, 则 让 设 备 震 动, 显 示 的 命 中 数 加 1, 地 鼠 随 机 移 动 到 一 个 新 位 置 ; 如 果 手 指 直 接 触 摸 到 屏 幕 但 没 点 击 中 地 鼠, 则 显 示 失 败 数 加 1; 点 击 重 新 开 始 按 钮, 游 戏 重 新 开 始, 命 中 和 失 败 的 计 数 归 零 学 习 内 容
本 章 内 容 覆 盖 了 以 下 的 组 件 及 概 念 : ImageSprite 组 件 : 具 有 触 感 的 可 移 动 图 像 ; Canvas 组 件 : 容 纳 ImageSprite 的 平 台 ; Clock 组 件 : 用 来 计 时, 让 sprite 随 即 移 动 ; Sound 组 件 : 击 中 地 鼠 时 产 生 震 动 ; Button 组 件 : 开 始 新 游 戏 ; Procedures: 用 来 实 现 一 系 列 的 指 令, 可 以 重 复 调 用, 如 移 动 地 鼠 ; 产 生 随 机 数 ; 使 用 加 法 块 (+) 及 减 法 块 (-) 准 备 开 始 登 陆 App Inventor 网 站, 开 始 新 项 目 MoleMash, 将 屏 幕 标 题 (title) 设 为 打 地 鼠, 并 连 接 到 测 试 设 备 下 载 地 鼠 图 片 mole.png 下 载 方 法 : 控 制 键 + 单 击 (Mac) 或 单 击 右 键 (Windows) 并 选 择 图 片 另 存 为 或 类 似 选 项 下 载 成 功 后, 在 设 计 器 组 件 列 表 下 方 的 Media 部 分, 单 击 Upload file, 找 到 刚 下 载 的 文 件 mole.png 并 上 传 到 App Inventor 中 设 计 组 件 创 建 打 地 鼠 游 戏 需 要 以 下 组 件 : Canvas 组 件 : 用 来 限 定 游 戏 中 地 鼠 的 活 动 区 域 ;
ImageSprite 组 件 : 用 来 显 示 地 鼠 图 片, 随 机 移 动, 并 具 有 触 感 ; Sound 组 件 : 当 地 鼠 被 触 摸 到 时, 发 出 震 动 ; Label 组 件 : 用 来 显 示 命 中 : 失 败 : 以 及 命 中 失 败 的 次 数 ; HorizontalArrangements 组 件 : 用 来 放 置 Label 组 件, 使 组 件 的 布 局 合 理 ; Button 组 件 : 用 来 将 命 中 及 失 败 次 数 归 零 ( 重 新 开 始 游 戏 ); Clock 组 件 : 使 地 鼠 每 秒 钟 随 机 移 动 一 次 表 3-1 显 示 了 应 用 中 用 到 的 全 部 组 件 表 3-1 打 地 鼠 应 用 中 的 全 部 组 件 列 表 组 件 类 型 组 件 种 类 命 名 作 用 Canvas ImageSprite Drawing and Ani mation Drawing and Ani mation Canvas1 Mole ImageSprite 的 容 器 用 户 点 击 的 目 标 Button User Interface ResetButton 重 新 设 置 得 分 Clock User Interface Clock1 控 制 地 鼠 的 移 动 频 率 Sound Media Sound1 当 地 鼠 被 击 中 时 震 动 Label User Interface HitsLabel 显 示 文 字 击 中 : Label User Interface HitsCountLabel 显 示 击 中 次 数 HorizontalArrang ement Layout HorizontalArrang ement1 放 置 HitsLabel 及 HitsCountL abel Label User Interface MissesLabel 显 示 文 字 失 败 : Label User Interface MissesCountLabel 显 示 失 败 次 数 HorizontalArrang ement Layout HorizontalArrang ement2 放 置 MissesLabel 及 MissesC ountlabel 设 置 活 动 组 件 本 节 将 设 置 游 戏 中 所 需 的 活 动 组 件, 下 节 再 来 设 置 显 示 分 数 的 组 件
1. 找 到 Palette->Drawing and Animation->Canvas 组 件, 拖 入 预 览 窗 口, 采 用 其 默 认 名 称 Canvas1, 设 置 Width 属 性 为 Fill parent, 即 与 屏 幕 等 宽, 设 置 Height 属 性 为 300 像 素 ; 2. 找 到 Palette->Drawing and Animation->ImageSprite, 将 ImageSprite 组 件 拖 入 到 Canvas1 中 的 任 何 位 置, 在 组 件 列 表 底 部 单 击 rename, 改 名 为 Mole, 设 置 其 Picture 属 性 为 之 前 上 传 的 mole.png; 3. 找 到 Palette->User Interface->Button, 拖 动 Button 组 件 放 在 Canvas1 下 面, 改 名 为 ResetButton, 并 设 置 其 Text 属 性 为 重 新 开 始 ; 4. 找 到 Palette->User Interface->Clock, 拖 入 Clock 组 件, 它 将 落 在 预 览 窗 口 下 方 的 非 可 是 组 件 区 域 ; 5. 找 到 Palette->Media->Sound, 拖 入 Sound 组 件, 它 也 将 落 在 非 可 视 组 件 区 域 现 在 组 件 设 计 器 看 起 来 应 该 如 图 3-2( 地 鼠 的 位 置 有 可 能 不 同 )
图 3-2 组 件 设 计 器 视 图 中 的 所 有 活 动 组 件 布 置 Label 组 件 现 在 设 置 显 示 用 户 得 分 的 组 件, 即, 显 示 命 中 与 失 败 次 数 的 组 件 1. 找 到 Palette->Layout->HorizontalArrangement, 拖 动 组 件 放 在 重 新 启 动 按 钮 的 下 方, 保 留 HorizontalArrangement1 的 默 认 名 称 ;
2. 从 Palette->User Interface 中 拖 动 两 个 Label 组 件 到 HorizontalArrangement1 中 ; 将 左 侧 Label 改 名 为 HitsLabel, 设 置 其 Text 属 性 为 命 中 : ( 确 保 冒 号 后 有 一 个 空 格 ); 将 右 侧 Label 改 名 为 HitsCountLabel, 设 置 其 Text 属 性 为 0 ; 3. 拖 入 第 二 个 HorizontalArrangement, 将 其 放 在 HorizontalArrangement1 下 面 ; 4. 将 两 个 Label 拖 放 在 HorizontalArrangement2 中 ; 左 侧 Label 改 名 为 MissesLabel, 设 置 其 Text 属 性 为 失 败 : ( 确 保 冒 号 后 有 一 个 空 格 ); 右 侧 Label 改 名 为 MissesCountLabel, 设 置 其 Text 属 性 为 0 你 的 屏 幕 看 起 来 如 图 3-3
图 3-3 组 件 设 计 器 视 图 中 打 地 鼠 应 用 的 所 有 组 件 为 组 件 添 加 行 为 组 件 已 经 创 建 完 成, 下 面 切 换 到 块 编 辑 器 来 实 现 程 序 的 行 为 设 置 的 目 标 :1 让 地 鼠 每 秒 钟 在 Canvas1 上 随 机 移 动 一 次 ;2 用 户 拍 打 这 只 随 机 移 动 的 地 鼠, 应 用 显 示 用 户 命 中 或 失 败 的 次 数 ( 注 : 建 议 用 手 指 而 不 是 木 槌 拍 打!); 按 下 重 新 启 动 按 钮 命 中 及 失 败 次 数 归 零
移 动 地 鼠 在 迄 今 为 止 完 成 的 应 用 中, 曾 经 调 用 过 内 置 过 程, 如 HelloPurr 中 的 Sound1.Vibrate( 震 动 ) 假 如 App Inventor 中 有 一 个 内 置 过 程, 可 以 将 ImageSprite 移 动 到 屏 幕 上 的 某 个 随 机 位 置, 那 岂 不 是 很 好? 可 惜 没 有, 不 过 我 们 可 以 自 己 来 创 建 过 程! 就 像 内 置 过 程 一 样, 自 己 创 建 的 过 程 会 显 示 在 Procedures 抽 屉 中, 需 要 时 可 以 随 时 调 用 它 具 体 来 说, 创 建 一 个 名 为 MoveMole 的 过 程, 让 地 鼠 在 屏 幕 上 移 动 到 某 个 随 机 位 置 游 戏 开 始 时 调 用 一 次 MoveMole 过 程, 当 用 户 成 功 地 点 击 到 地 鼠 后, 每 秒 钟 执 行 一 次 该 过 程 创 建 MoveMole 过 程 要 理 解 地 鼠 如 何 移 动, 需 要 了 解 Android 的 图 形 定 位 机 制 Canvas( 以 及 Screen) 可 以 看 作 是 由 x( 水 平 ) 坐 标 和 y( 垂 直 ) 坐 标 织 成 的 网 格, 其 左 上 角 的 (x,y) 坐 标 为 (0,0) x 坐 标 向 右 为 增 大, y 坐 标 向 下 为 增 大, 如 图 3-4 所 示 一 个 ImageSprite 的 x y 属 性 表 示 它 左 上 角 的 位 置, 因 此 当 地 鼠 位 于 屏 幕 左 上 角 时, 他 的 x 和 y 值 都 是 0
图 3-4 屏 幕 上 Mole 的 位 置 坐 标 高 度 和 宽 度 信 息,x 坐 标 及 宽 度 以 蓝 色 表 示,y 坐 标 和 高 度 以 橙 色 表 示 为 了 将 地 鼠 的 移 动 限 制 在 屏 幕 之 内, 要 确 定 x 和 y 的 最 大 值, 这 要 用 到 地 鼠 Mole 和 画 布 Canvas1 的 Width( 宽 度 ) 及 Height( 高 度 ) 属 性 ( 地 鼠 的 Width 和 Height 属 性 值 与 上 传 的 图 片 的 大 小 相 同, 而 在 创 建 Canvas1 时, 你 设 置 的 高 度 是 300 像 素, 宽 度 为 Fill parent, 即 等 于 它 的 父 容 器 屏 幕 的 宽 度 ) 如 果 地 鼠 图 片 的 宽 度 是 36 像 素, 画 布 宽 度 是 200 像 素, 那 么 Mole 的 x 坐 标 最 低 可 以 为 0( 靠 近 屏 幕 左 侧 边 缘 ), 而 最 大 为 164(200-36, 或 Canvas1.Width - Mole.Width), 这 样 才 能 保 证 Mole 不 超 出 屏 幕 的 右 侧 边 缘 同 样,Mole 顶 部 的 y 坐 标 范 围 可 从 0 到 Canvas1.Height - Mole.Height 图 3-5 显 示 了 创 建 的 MoveMole 过 程, 图 中 标 有 详 细 注 释 ( 可 以 有 选 择 地 添 加 到 过 程 中 )
为 了 随 机 地 放 置 Mole,x 坐 标 要 在 0 到 Canvas1.Width - Mole.Width 的 范 围 内 选 择, 同 样,y 坐 标 要 在 0 到 Canvas1.Height - Mole.Height 的 范 围 内 使 用 Math 抽 屉 里 的 内 置 过 程 random integer 生 成 一 个 随 机 整 数, 将 from 参 数 从 改 默 的 1 改 为 0, 同 样 修 改 to 参 数, 如 图 3-5 所 示 图 3-5A MoveMole 过 程, 用 于 将 Mole 放 在 一 个 随 机 的 位 置 上 按 如 下 步 骤 创 建 过 程 : 1. 找 到 Procedures: 单 击 块 编 辑 器 中 的 Procedures 抽 屉 ; 2. 得 到 to procedure: 在 Procedures 抽 屉 中 点 击 to procedure 块 ( 不 带 result 的 to procedure); 3. 设 置 过 程 名 称 : 单 击 块 中 的 文 字 procedure 并 输 入 MoveMole ; 4. 移 动 Mole: 单 击 Mole 抽 屉, 将 call Mole.MoveTo 块 拖 到 procedure 块 中 do 的 右 侧 ; 注 意 : 我 们 还 需 要 提 供 x 和 y 的 坐 标 ; 5. 设 定 Mole 的 x 坐 标 : 如 前 所 述,x 坐 标 范 围 在 0 与 Canvas1.Width - Mole.Width 之 间 : 点 击 Math 抽 屉 ; 拖 出 random integer from 块, 将 左 侧 插 头 ( 突 起 ) 插 入 call Mole.MoveTo 块 的 x 插 槽 ;
点 选 from 之 后 的 数 字 1 并 输 入 0; 丢 弃 数 字 100: 点 击 该 块, 再 按 键 盘 上 的 Del 或 Delete 键, 或 直 接 拖 入 垃 圾 箱 ; 点 击 Math 抽 屉, 将 一 个 减 法 块 (-) 拖 入 to 插 槽 ; 点 击 Canvas1 抽 屉, 向 下 滚 动 直 到 看 见 Canvas1.BackgroundColor, 将 其 拖 入 到 减 法 块 - 的 左 侧, 然 后 从 BackgroundColor 所 在 的 下 拉 菜 单 中 选 择 Width 选 项 ; 同 样, 点 击 Mole 抽 屉 并 拖 入 Mole.Enabled 块, 然 后 从 Enabled 块 所 在 的 下 拉 菜 单 中 选 择 Width 选 项, 并 将 它 插 入 到 - 右 侧 的 插 槽 中 ; 6. 按 类 似 步 骤 设 定 y 坐 标, 应 该 是 一 个 从 0 到 Canvas1.Height - Mole.Height 的 随 机 整 数 ; 7. 对 图 3-5A( 行 内 输 入 ) 或 3-5B( 外 展 输 入 ) 检 查 操 作 结 果 8. random integer from to 块 的 external inputs ( 外 展 输 入 ) 方 式 : 右 键 点 击 random 块, 选 择 列 表 第 三 项 external inputs; 如 果 想 恢 复 行 内 输 入, 右 键 点 击 random 块, 选 择 inline inputs 图 3-5B MoveMole 过 程, 用 于 将 Mole 放 在 一 个 随 机 的 位 置 上 在 应 用 启 动 时 调 用 MoveMole 过 程
已 经 完 成 了 MoveMole 过 程, 现 在 该 调 用 它 了 对 于 程 序 员 来 说, 最 熟 悉 的 事 情 就 是 在 应 用 启 动 的 同 时 执 行 某 些 指 令, 块 Screen1.Initialize 就 是 专 为 这 个 目 的 而 设 计 的 : 1. 点 击 Screen1 抽 屉, 并 拖 出 Screen1.Initialize 块 ; 2. 单 击 Procedures 抽 屉, 你 会 看 到 一 个 call MoveMole 块 ( 这 很 有 趣 : 你 自 己 创 建 了 一 个 新 块, 不 是 吗?!) 把 它 拖 入 Screen1.Initialize, 如 图 3-6 所 示 图 3-6 在 应 用 启 动 时 调 用 MoveMole 过 程 每 秒 钟 调 用 一 次 MoveMole 过 程 要 让 地 鼠 每 一 秒 移 动 一 次, 需 要 用 到 Clock 组 件 设 置 Clock1 的 TimerInterval 属 性 为 其 默 认 值 1000( 毫 秒 ), 即 1 秒, 我 们 称 每 秒 一 次 的 计 时 为 计 时 器 的 心 跳 这 意 味 着, 在 Clock1.Timer 块 中, 无 论 设 定 什 么 动 作, 它 都 会 随 着 计 时 器 的 心 跳, 每 秒 钟 执 行 一 次 以 下 是 具 体 设 置 : 1. 单 击 Clock1 抽 屉, 并 拖 出 Clock1.Timer; 2. 单 击 Procedures 抽 屉, 将 call MoveMole 块 拖 到 Clock1.Timer 块 中, 如 图 3-7 所 示
图 3-7 计 时 器 开 始 计 时 后, 每 次 心 跳 ( 每 秒 ) 都 会 调 用 一 次 MoveMole 过 程 如 果 你 觉 得 心 跳 得 太 快 或 太 慢, 可 以 在 组 件 设 计 器 中 改 变 Clock1 的 TimerInterval 属 性, 来 增 加 或 减 小 地 鼠 的 移 动 频 率 记 录 成 绩 刚 才 我 们 创 建 了 两 个 Label: 初 始 值 为 0 的 HitsCountsLabel 和 MissesCountsLabel, 希 望 以 此 来 记 录 用 户 的 成 绩 : 当 用 户 命 中 Mole 一 次, 或 失 败 一 次 ( 直 接 拍 打 到 屏 幕 ) 时, 对 应 Label 中 的 数 字 增 加, 为 此 要 用 到 Canvas1.Touched 块, 它 表 示 Canvas 被 触 摸 到, 并 记 录 了 触 摸 点 的 x 和 y 坐 标 ( 我 们 不 必 关 心 ), 以 及 是 否 碰 到 了 sprite( 这 是 我 们 关 心 的 ) 图 3-8 显 示 了 即 将 创 建 的 代 码 图 3-8 触 碰 到 Canvas1 时, 让 命 中 (HitsCountLabel) 或 失 败 (MissesCountLabel) 次 数 递 增 图 3-8 可 以 理 解 为 : 当 触 碰 到 canvas 时, 检 查 sprite 是 否 也 被 碰 到 应 用 中 只 有 一 个 sprite, 即 Mole, 如 果 碰 到 Mole, 则 HitsCountLabel.Text 中 的 数 字 +1, 否 则,MissesCountLabel.Text 中 的 数 字 +1( 如 果 没 碰 到 sprite, 则 touchedsprite 的 值 为 false )
下 面 介 绍 如 何 创 建 这 些 块 : 1. 点 击 Canvas1 抽 屉, 并 拖 出 Canvas1.Touched; 2. 单 击 Control 抽 屉, 拖 出 Ifelse 块 ( 先 拖 入 if 块, 然 后 为 其 添 加 else 块 : 点 击 if 左 边 的 蓝 色 方 块, 在 弹 出 框 中 将 else 块 拖 入 if 块 ), 并 放 入 Canvas1.Touched 块 中 ; 3. 从 Variables 抽 屉 中 拖 出 get 块, 放 入 ifelse 的 if 插 槽 内, 选 择 下 拉 菜 单 中 的 touchedsprite 选 项 ; 或 者 将 鼠 标 悬 停 在 when Canvas.Touched 块 的 参 数 touchedsprite 上, 从 中 获 取 get touchedsprite 块 ; 4. 按 照 我 们 的 设 想, 如 果 if 检 测 成 功 ( 即 Mole 被 触 摸 到 ), 则 HitsCountLabel.Text 递 增 : 从 HitsCountLabel 抽 屉 里 拖 出 set HitsCountLabel.Text to 块 并 放 入 then 的 右 边 ; 点 击 Math 抽 屉, 拖 出 一 个 加 号 (+), 将 其 放 在 to 插 槽 中 ; 点 击 HitsCountLabel 抽 屉, 拖 动 HitsCountLabel.Text 块 到 + 的 左 边 ; 点 击 Math 抽 屉, 并 拖 动 一 个 0 块 到 + 的 右 边, 将 0 改 为 1 ; 5. 在 ifelse 块 的 else 部 分, 对 MissesCountLabel 块 重 复 步 骤 4 测 试 : 测 试 你 的 新 代 码 : 在 设 备 上 触 摸 Canvas, 命 中 或 错 过 地 鼠, 看 看 分 数 有 什 么 变 化 过 程 抽 象
计 算 机 科 学 的 重 要 手 段 之 一, 就 是 命 名 然 后 调 用 一 组 指 令 ( 如 MoveMole), 这 种 能 力 被 称 为 过 程 抽 象 之 所 以 叫 做 抽 象, 是 因 为 过 程 的 调 用 者 ( 在 实 际 项 目 中, 很 有 可 能 不 是 过 程 的 开 发 者 ) 只 需 要 知 道 过 程 的 功 能 ( 如 移 动 地 鼠 ), 而 不 需 要 知 道 过 程 的 实 现 方 法 ( 生 成 两 个 随 机 整 数 ) 如 果 没 有 过 程 抽 象, 不 可 能 实 现 那 些 大 型 程 序, 因 为 它 们 的 代 码 量 太 大, 对 个 人 来 说 是 力 所 不 及 的, 这 一 点 与 现 实 世 界 中 的 劳 动 分 工 相 类 似 例 如, 不 同 的 工 程 师 设 计 出 汽 车 的 不 同 部 件, 没 有 人 了 解 所 有 的 细 节, 而 司 机 只 需 要 了 解 接 口 ( 例 如, 踩 下 制 动 踏 板 把 车 停 下 来 ), 而 无 需 了 解 如 何 实 现 这 些 接 口 与 复 制 和 粘 贴 代 码 相 比, 过 程 抽 象 的 优 势 在 于 : 由 于 过 程 的 代 码 独 立 于 其 它 部 分 的 程 序, 因 此 更 易 于 对 过 程 的 测 试 ; 如 果 代 码 中 有 错 误, 只 需 要 对 局 部 进 行 修 改 ; 如 果 需 要 改 变 过 程 的 实 现 ( 或 功 能 ), 如 确 保 地 鼠 不 连 续 出 现 在 同 一 个 位 置, 只 需 要 修 改 一 处 的 代 码 ; 可 以 将 过 程 汇 集 到 一 个 程 序 库 中, 以 便 在 不 同 的 程 序 中 使 用 ( 遗 憾 的 是 App Inventor 暂 时 不 支 持 这 项 功 能 ) 将 大 块 代 码 拆 分 成 代 码 片 段, 有 助 于 对 应 用 做 深 入 剖 析, 并 加 以 实 现 ( 分 而 治 之 ) 给 过 程 一 个 有 意 义 的 命 名, 将 有 助 于 提 高 代 码 的 可 读 性, 更 易 被 别 人 ( 或 一 个 月 后 的 自 己 ) 读 懂 ; 在 后 面 的 章 节 中, 还 将 学 到 过 程 更 加 强 大 的 功 能 : 添 加 参 数, 提 供 返 回 值, 以 及 调 用 过 程 本 身 有 关 内 容 请 参 见 第 21 章
重 置 分 数 朋 友 看 到 你 玩 MoleMash, 他 可 能 也 想 试 试 身 手, 所 以 最 好 能 让 成 绩 归 零 根 据 前 面 学 过 的 内 容, 不 经 提 示 你 也 有 能 力 把 它 做 出 来 阅 读 之 前 动 脑 筋 试 试 看 我 们 要 在 ResetButton.Click 块 中 设 置 HitsCountLabel.Text 和 MissesCountLabel.Text 的 值 为 0 如 图 3-9 所 示 图 3-9 按 下 Reset 按 钮 让 命 中 次 数 (HitsCountLabel) 和 失 败 次 数 (MissesCountLabel) 归 零 此 处 提 供 一 个 技 巧, 来 快 速 建 立 ResetButton.Click 的 事 件 处 理 程 序 : 在 工 作 区 直 接 输 入 0 并 回 车, 将 生 成 数 字 块 0, 等 同 于 从 Math 抽 屉 中 拖 出 ( 这 种 输 入 方 式 对 其 他 块 也 同 样 有 效 ) 测 试 : 开 始 游 戏, 尝 试 多 次 命 中 及 错 过 地 鼠, 然 后 按 下 重 新 启 动 按 钮 添 加 触 摸 地 鼠 行 为 我 们 希 望 在 触 摸 到 地 鼠 时, 设 备 能 够 振 动, 这 要 用 到 Sound1.Vibrate 块 如 图 3-10 所 示
图 3-10 碰 到 地 鼠 时 让 设 备 短 暂 振 动 (100 毫 秒 ) 测 试 : 当 你 在 设 备 上 实 际 触 摸 到 地 鼠 时, 看 看 振 动 的 效 果 如 何 如 果 你 觉 得 振 动 时 间 过 长 或 过 短, 可 以 修 改 Sound1.Vibrate 块 的 毫 秒 数 完 整 的 MoleMash 应 用 图 3-11 中 描 述 了 完 整 的 MoleMash 应 用 中 所 有 的 块 图 3-11 完 整 的 MoleMash 应 用 改 进 对 MoleMash 应 用 还 可 以 做 如 下 补 充 :
添 加 按 钮, 让 用 户 可 以 控 制 地 鼠 的 移 动 速 度 ; 添 加 一 个 Label, 随 时 显 示 地 鼠 出 现 ( 或 移 动 ) 的 次 数 ; 添 加 另 一 个 ImageSprite, 如 一 朵 花 的 图 片 : 用 户 不 许 碰 到 它, 如 果 碰 到 将 会 受 到 惩 罚, 减 少 得 分 或 结 束 游 戏 ; 用 ContactPicker 组 件 从 用 户 手 机 的 电 话 簿 中 选 择 图 片, 来 替 代 地 鼠 图 片 小 结 本 章 介 绍 了 一 些 非 常 有 用 的 技 巧, 适 用 于 普 通 应 用, 更 适 用 于 游 戏 : Canvas 组 件 使 用 了 直 角 坐 标 系, 其 中 x 表 示 水 平 方 向 ( 从 左 边 的 0 到 右 边 的 Canvas.Width -1),y 表 示 垂 直 方 向 ( 从 顶 部 的 0 到 底 部 的 Canvas.Height -1) 从 Canvas 的 高 度 和 宽 度 中 减 去 某 个 ImageSprite 的 高 度 和 宽 度, 这 个 范 围 可 以 确 保 sprite 在 画 布 上 完 整 地 显 示 ; 利 用 Canvas 和 ImageSprite 组 件 的 Touched 方 法 来 实 现 对 设 备 触 感 的 应 用 ; 创 建 实 时 交 互 应 用 : 不 仅 可 以 对 用 户 的 操 作 做 出 实 时 响 应, 也 可 以 对 设 备 内 部 的 计 时 器 做 出 响 应 具 体 地 说,Clock.Interval 属 性 用 于 设 定 计 时 器 的 心 跳 频 率, 这 个 频 率 也 可 以 用 于 控 制 ImageSprite ( 或 其 它 ) 组 件 的 移 动 ; Label 可 用 于 显 示 得 分, 根 据 玩 家 的 操 作 结 果, 得 分 会 相 应 升 高 ( 或 下 降 );
通 过 Sound.Vibrate 方 法 对 用 户 的 触 摸 事 件 进 行 反 馈, 让 设 备 震 动 一 定 的 毫 秒 数 ; 不 仅 可 以 调 用 内 置 过 程, 也 可 以 通 过 给 一 组 块 设 定 名 称 (MoveMole), 来 创 建 自 己 的 过 程, 这 些 过 程 也 可 以 像 内 置 过 程 一 样 被 调 用, 这 就 是 所 谓 的 过 程 抽 象, 在 计 算 机 科 学 中 这 是 一 个 非 常 重 要 的 思 想, 可 以 实 现 代 码 的 复 用, 也 使 得 创 建 复 杂 应 用 成 为 可 能 ; 利 用 Math 抽 屉 中 的 random integer( 随 机 整 数 ) 块, 可 以 产 生 不 可 预 知 行 为, 让 游 戏 每 次 开 始 时 都 有 所 不 同 在 第 5 章 ( 瓢 虫 快 跑 ) 中, 将 了 解 更 多 的 游 戏 制 作 技 巧, 包 括 移 动 中 的 ImageSprite 组 件 之 间 的 碰 撞 检 测