刘 哇 勇 的 部 落 格 博 客 园 首 页 订 阅 管 理 随 笔 - 80 文 章 - 1 评 论 - 1494 GitHub 主 页 @ 刘 哇 勇 liuwayong(at)gmail.com 昵 称 : 刘 哇 勇 园 龄 :3 年 8 个 月 荣 誉 : 推 荐 博 客 粉 丝 :1760 关 注 :10 + 加 关 注 随 笔 分 类 (85) CSS(8) DB(1) HTML5(13) JavaScript(13) jquery(12) MVC(2) node.js(1) Others(28) three.js(1) 札 记 (6) 如 何 开 发 一 个 简 单 的 HTML5 Canvas 小 游 戏 原 文 :How to make a simple HTML5 Canvas game 想 要 快 速 上 手 HTML5 Canvas 小 游 戏 开 发? 下 面 通 过 一 个 例 子 来 进 行 手 把 手 教 学 ( 如 果 你 怀 疑 我 的 资 历, A Wizard's Lizard 这 个 游 戏 的 半 数 以 上 开 发 是 由 我 完 成 的 ) 我 们 直 接 来 看 源 码 里 的 game.js, 当 然 你 也 可 以 在 线 体 验 一 下 游 戏 先 游 戏 截 图 推 荐 排 行 榜 1. 好 的 用 户 界 面 - 界 面 设 计 的 一 些 技 巧 (42 9) 2. 前 端 不 为 人 知 的 一 面 -- 前 端 冷 知 识 集 锦 (245) 3. jquery 插 件 开 发 精 品 教 程, 让 你 的 jqu ery 提 升 一 个 台 阶 (174) 4. Chrome 控 制 台 不 完 全 指 南 (150) 5. 一 个.Net 程 序 员 关 于 学 习 的 思 考 顺 带 思 考 人 生 (119) 创 建 画 布 // Create the canvas var canvas = document.createelement("canvas"); var ctx = canvas.getcontext("2d"); canvas.width = 512; canvas.height = 480; document.body.appendchild(canvas); 首 先 我 们 需 要 创 建 一 张 画 布 作 为 游 戏 的 舞 台 这 里 通 过 JS 代 码 而 不 是 直 接 在 HTML 里 写 一 个 <canvas> 元 素 目 的 是 要 说 明 代 码 创 建 也 是 很 方 便 的 有 了 画 布 后 就 可 以 获 得 它 的 上 下 文 来 进 行 绘 图 了 然 后 我 们 还 设 置 了 画 布 大 小, 最 后 将 其 添 加 到 页 面 上 准 备 图 片 // 背 景 图 片 var bgready = false; var bgimage = new Image(); bgimage.onload = function () { bgready = true; ; bgimage.src = "images/background.png"; 6 游 戏 嘛 少 不 了 图 片 的, 所 以 我 们 先 加 载 一 些 图 片 先 简 便 起 见, 这 里 仅 创 建 简 单 的 图 片 对 象, 而 不 是 专 门 写 一 个 类 或 者 Helper 来 做 图 片 加 载 bgready 这 个 变 量 用 来 标 识
图 片 是 否 已 经 加 载 完 成 从 而 可 以 放 心 地 使 用 了, 因 为 如 果 在 图 片 加 载 未 完 成 情 况 下 进 行 绘 制 是 会 报 错 的 整 个 游 戏 中 需 要 用 到 的 三 张 图 片 : 背 景, 英 雄 及 怪 物 我 们 都 用 上 面 的 方 法 来 处 理 游 戏 对 象 // 游 戏 对 象 var hero = { speed: 256, // 每 秒 移 动 的 像 素 x: 0, y: 0 ; var monster = { x: 0, y: 0 ; var monsterscaught = 0; 现 在 定 义 一 些 对 象 将 在 后 面 用 到 我 们 的 英 雄 有 一 个 speed 属 性 用 来 控 制 他 每 秒 移 动 多 少 像 素 怪 物 游 戏 过 程 中 不 会 移 动, 所 以 只 有 坐 标 属 性 就 够 了 monsterscaught 则 用 来 存 储 怪 物 被 捉 住 的 次 数 处 理 用 户 的 输 入 // 处 理 按 键 var keysdown = {; addeventlistener("keydown", function (e) { keysdown[e.keycode] = true;, false); addeventlistener("keyup", function (e) { delete keysdown[e.keycode];, false); 现 在 开 始 处 理 用 户 的 输 入 ( 对 初 次 接 触 游 戏 开 发 的 前 端 同 学 来 说, 这 部 分 开 始 可 能 就 需 要 一 些 脑 力 了 ) 在 前 端 开 发 中, 一 般 是 用 户 触 发 了 点 击 事 件 然 后 才 去 执 行 动 画 或 发 起 异 步 请 求 之 类 的, 但 这 里 我 们 希 望 游 戏 的 逻 辑 能 够 更 加 紧 凑 同 时 又 要 及 时 响 应 输 入 所 以 我 们 就 把 用 户 的 输 入 先 保 存 下 来 而 不 是 立 即 响 应 为 此, 我 们 用 keysdown 这 个 对 象 来 保 存 用 户 按 下 的 键 值 ( keycode ), 如 果 按 下 的 键 值 在 这 个 对 象 里, 那 么 我 们 就 做 相 应 处 理 开 始 一 轮 游 戏 // 当 用 户 抓 住 一 只 怪 物 后 开 始 新 一 轮 游 戏 var reset = function () { hero.x = canvas.width / 2; hero.y = canvas.height / 2; ; // 将 新 的 怪 物 随 机 放 置 到 界 面 上 monster.x = 32 + (Math.random() * (canvas.width 64)); monster.y = 32 + (Math.random() * (canvas.height 64)); reset 方 法 用 于 开 始 新 一 轮 和 游 戏, 在 这 个 方 法 里 我 们 将 英 雄 放 回 画 布 中 心 同 时 将 怪 物 放 到 一 个 随 机 的 地 方 更 新 对 象 // 更 新 游 戏 对 象 的 属 性 var update = function (modifier) { if (38 in keysdown) { // 用 户 按 的 是 hero.y = hero.speed * modifier; if (40 in keysdown) { // 用 户 按 的 是 hero.y += hero.speed * modifier;
if (37 in keysdown) { // 用 户 按 的 是 hero.x = hero.speed * modifier; if (39 in keysdown) { // 用 户 按 的 是 hero.x += hero.speed * modifier; ; // 英 雄 与 怪 物 碰 到 了 么? if ( hero.x <= (monster.x + 32) && monster.x <= (hero.x + 32) && hero.y <= (monster.y + 32) && monster.y <= (hero.y + 32) ) { ++monsterscaught; reset(); 这 就 是 游 戏 中 用 于 更 新 画 面 的 update 函 数, 会 被 规 律 地 重 复 调 用 首 先 它 负 责 检 查 用 户 当 前 按 住 的 是 中 方 向 键, 然 后 将 英 雄 往 相 应 方 向 移 动 有 点 费 脑 力 的 或 许 是 这 个 传 入 的 modifier 变 量 你 可 以 在 main 方 法 里 看 到 它 的 来 源, 但 这 里 还 是 有 必 要 详 细 解 释 一 下 它 是 基 于 1 开 始 且 随 时 间 变 化 的 一 个 因 子 例 如 1 秒 过 去 了, 它 的 值 就 是 1, 英 雄 的 速 度 将 会 乘 以 1, 也 就 是 每 秒 移 动 256 像 素 ; 如 果 半 秒 钟 则 它 的 值 为 0.5, 英 雄 的 速 度 就 乘 以 0.5 也 就 是 说 这 半 秒 内 英 雄 以 正 常 速 度 一 半 的 速 度 移 动 理 论 上 说 因 为 这 个 update 方 法 被 调 用 的 非 常 快 且 频 繁, 所 以 modifier 的 值 会 很 小, 但 有 了 这 一 因 子 后, 不 管 我 们 的 代 码 跑 得 快 慢, 都 能 够 保 证 英 雄 的 移 动 速 度 是 恒 定 的 现 在 英 雄 的 移 动 已 经 是 基 于 用 户 的 输 入 了, 接 下 来 该 检 查 移 动 过 程 中 所 触 发 的 事 件 了, 也 就 是 英 雄 与 怪 物 相 遇 这 就 是 本 游 戏 的 胜 利 点, monsterscaught +1 然 后 重 新 开 始 新 一 轮 渲 染 物 体 // 画 出 所 有 物 体 var render = function () { if (bgready) { ctx.drawimage(bgimage, 0, 0); if (heroready) { ctx.drawimage(heroimage, hero.x, hero.y); if (monsterready) { ctx.drawimage(monsterimage, monster.x, monster.y); ; // 计 分 ctx.fillstyle = "rgb(250, 250, 250)"; ctx.font = "24px Helvetica"; ctx.textalign = "left"; ctx.textbaseline = "top"; ctx.filltext("monsterrs caught: " + monsterscaught, 32, 32); 之 前 的 工 作 都 是 枯 燥 的, 直 到 你 把 所 有 东 西 画 出 来 之 后 首 先 当 然 是 把 背 景 图 画 出 来 然 后 如 法 炮 制 将 英 雄 和 怪 物 也 画 出 来 这 个 过 程 中 的 顺 序 是 有 讲 究 的, 因 为 后 画 的 物 体 会 覆 盖 之 前 的 物 体 这 之 后 我 们 改 变 了 一 下 Canvas 的 绘 图 上 下 文 的 样 式 并 调 用 filltext 来 绘 制 文 字, 也 就 是 记 分 板 那 一 部 分 本 游 戏 没 有 其 他 复 杂 的 动 画 效 果 和 打 斗 场 面, 绘 制 部 分 大 功 告 成! 主 循 环 函 数 // 游 戏 主 函 数 var main = function () { var now = Date.now();
var delta = now then; update(delta / 1000); render(); then = now; ; // 立 即 调 用 主 函 数 requestanimationframe(main); 上 面 的 主 函 数 控 制 了 整 个 游 戏 的 流 程 先 是 拿 到 当 前 的 时 间 用 来 计 算 时 间 差 ( 距 离 上 次 主 函 数 被 调 用 时 过 了 多 少 毫 秒 ) 得 到 modifier 后 除 以 1000( 也 就 是 1 秒 中 的 毫 秒 数 ) 再 传 入 update 函 数 最 后 调 用 render 函 数 并 且 将 本 次 的 时 间 保 存 下 来 关 于 游 戏 中 循 环 更 新 画 面 的 讨 论 可 参 见 Onslaught! Arena Case Study 关 于 循 环 的 进 一 步 解 释 // requestanimationframe 的 浏 览 器 兼 容 性 处 理 var w = window; requestanimationframe = w.requestanimationframe w.webkitrequestanimationframe w.msrequestanimationframe w.mozrequestanimationframe; 如 果 你 不 是 完 全 理 解 上 面 的 代 码 也 没 关 系, 我 只 是 觉 得 拿 出 来 解 释 一 下 总 是 极 好 的 为 了 循 环 地 调 用 main 函 数, 本 游 戏 之 前 用 的 是 setinterval 但 现 今 已 经 有 了 更 好 的 方 法 那 就 是 requestanimationframe 使 用 新 方 法 就 不 得 不 考 虑 浏 览 器 兼 容 性 上 面 的 垫 片 就 是 出 于 这 样 的 考 虑, 它 是 Paul Irish 博 客 原 版 的 一 个 简 化 版 本 启 动 游 戏! // 少 年, 开 始 游 戏 吧! var then = Date.now(); reset(); main(); 总 算 完 成 了, 这 是 本 游 戏 最 后 一 段 代 码 了 先 是 设 置 一 个 初 始 的 时 间 变 量 then 用 于 首 先 运 行 main 函 数 使 用 然 后 调 用 reset 函 数 来 开 始 新 一 轮 游 戏 ( 如 果 你 还 记 得 的 话, 这 个 函 数 的 作 用 是 将 英 雄 放 到 画 面 中 间 同 时 将 怪 物 放 到 随 机 的 地 方 以 方 便 英 雄 去 捉 它 ) 到 此, 相 信 你 已 经 掌 握 了 开 发 一 个 简 单 H5 小 游 戏 需 要 的 基 本 功 了 玩 玩 这 个 游 戏 或 者 下 载 代 码 自 己 研 究 研 究 吧 :) Feel free to repost but keep the link to this page please! 分 类 : HTML5 标 签 : Canvas, HTML5, game, 游 戏, 开 发 好 文 要 顶 关 注 我 收 藏 该 文 刘 哇 勇 关 注 - 10 粉 丝 - 1760 荣 誉 : 推 荐 博 客 + 加 关 注 «上 一 篇 : 如 果 把 编 程 语 言 当 成 座 驾» 下 一 篇 : 延 迟 求 值 - 如 何 让 Lo-Dash 再 提 速 x100? posted @ 2014-11-02 15:22 刘 哇 勇 阅 读 (11298) 评 论 (7) 编 辑 收 藏 评 论 列 表 #1 楼 2014-11-02 20:47 杜 少.
小 人 能 跑 到 外 边 去, 是 不 是 可 以 收 藏 +1, 评 论 +1 关 注 +0 那 个 支 持 (1) 反 对 (0) #2 楼 2014-11-03 08:17 青 出 于 蓝 看 到 有 一 个 reset 函 数, 可 以 说 明 一 下 吗? #3 楼 2014-12-02 17:49 silas_fff 楼 主 注 释 很 详 细, 游 戏 的 判 断 有 点 费 脑 ( 说 的 自 己 ), 最 好 还 是 渲 染 场 景 内 移 动, 这 是 稍 微 做 的 判 断 var update = function (modifier) { if (38 in keysdown) { // Player holding up hero.y -= hero.speed * modifier; if( hero.y < 32 ) hero.y = 32; if (40 in keysdown) { // Player holding down hero.y += hero.speed * modifier; if( hero.y >= 416) { hero.y = 416; if (37 in keysdown) { // Player holding left hero.x -= hero.speed * modifier; if( hero.x < 32){ hero.x = 32; if (39 in keysdown) { // Player holding right hero.x += hero.speed * modifier; if( hero.x > 448){ hero.x = 448; // Are they touching? if ( hero.x <= (monster.x + 32) && monster.x <= (hero.x + 32) && hero.y <= (monster.y + 32) && monster.y <= (hero.y + 32) ) { ++monsterscaught; reset(); ; #4 楼 [ 楼 主 ] 2014-12-02 23:47 刘 哇 勇 @ 青 出 于 蓝 引 用 看 到 有 一 个 reset 函 数, 可 以 说 明 一 下 吗?
`reset()` 用 来 将 英 雄 放 置 到 原 始 位 置 并 且 重 新 产 生 一 个 怪 我 #5 楼 [ 楼 主 ] 2014-12-02 23:47 刘 哇 勇 @ silas_fff 引 用 楼 主 注 释 很 详 细, 游 戏 的 判 断 有 点 费 脑 ( 说 的 自 己 ), 最 好 还 是 渲 染 场 景 内 移 动, 这 是 稍 微 做 的 判 断 va r update = function (modifier) { if (38 in keysdown) { // Player holding up hero.y -= hero.speed * modifier; if( hero.y < 32 ) hero.y = 32; if (40 in keysdown) { // Player holding down... 不 错 的 改 进! #6 楼 2015-11-12 18:19 船 长 1027 叼 炸 天 #7 楼 2016-02-18 08:46 bvjnn37629 厉 害, 对 我 太 有 用 了 HTML5 游 戏 http://sourcecode.itdadao.com/forum-html5-1.html 注 册 用 户 登 录 后 才 能 发 表 评 论, 请 登 录 或 注 册, 访 问 网 站 首 页 刷 新 评 论 刷 新 页 面 返 回 顶 部 推 荐 50 万 行 VC++ 源 码 : 大 型 组 态 工 控 电 力 仿 真 CAD 与 GIS 源 码 库 推 荐 融 云 即 时 通 讯 云 - 豆 果 美 食 Faceu 等 亿 级 APP 都 在 用 最 新 IT 新 闻 : 中 国 联 通 盈 利 警 告! 一 季 度 净 利 暴 跌 85% 索 尼 中 国 辟 谣 : 日 本 地 震 并 不 影 响 CMOS 产 能 特 斯 拉 将 为 其 车 主 提 供 30 天 自 动 驾 驶 免 费 试 用 服 务 MIT 开 发 人 工 智 能 可 检 测 85% 的 网 络 攻 击 bot 就 是 你 的 品 牌» 更 多 新 闻... 最 新 知 识 库 文 章 : 架 构 漫 谈 ( 九 ): 理 清 技 术 业 务 和 架 构 的 关 系 架 构 漫 谈 ( 八 ): 从 架 构 的 角 度 看 如 何 写 好 代 码 架 构 漫 谈 ( 七 ): 不 要 空 设 架 构 师 这 个 职 位, 给 他 实 权 架 构 漫 谈 ( 六 ): 软 件 架 构 到 底 是 要 解 决 什 么 问 题? 架 构 漫 谈 ( 五 ): 什 么 是 软 件» 更 多 知 识 库 文 章... Copyright 2016 刘 哇 勇
Click below to find more Mipaper at www.lcis.com.tw Mipaper at www.lcis.com.tw