From ff90e14c8d785ff74c8f687f82a5270832611e0e Mon Sep 17 00:00:00 2001 From: song Date: Thu, 21 Oct 2021 15:23:28 +0800 Subject: [PATCH] first commit --- README.md | 375 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..5778cd0 --- /dev/null +++ b/README.md @@ -0,0 +1,375 @@ +# 鸟妈妈回家 + +# 运行步骤 +1. git clone https://dd.tall.wiki/gitea/ccsens_fe/bird-go-home.git +2. 全局安装gulp npm i gulp -g +3. npm i 或者 yarn +4. 运行gulp +5. 运行vscode的Go Live +6. 部署服务器 dist目录 + + + +## 游戏介绍 + +“鸟妈妈回家”游戏用于 康复训练,上肢训练 + +游戏使用Adobe Animate制作,游戏包含如下几个模块: + ++ 主体:鸟、背景(山、云朵、树木等)、成功次数(也能代表得分) ++ 开始倒计时:开始面板、倒计时文本 ++ 返回按钮 ++ 难度级别 ++ 游戏计时 ++ 结束modal:界面面板、得分文本 ++ 测试模块 + + + +该游戏源文件,使用旧版的flash软件制作,转换成animate支持的canvas模式。 + +游戏原有动画均在图层中制作。包括游戏动作成功的字数,也在动画中制作。游戏动作设计调整难度较大,次数修改成本较高。目前是固定的20次,一般情况是够用。 + + + +## 目录结构说明 + +通过如下命令输出的目录结构: + +```bash +tree -I "node_modules|package-lock.json|yarn.lock" +``` + + + +```bash +│ .gitignore +│ .prettierrc +│ .svrxrc.js +│ dist.zip +│ gulpfile.js +│ package-lock.json +│ package.json +│ README.md +│ +├─dist +│ │ bird.js +│ │ index.html +│ │ main.js +│ │ +│ ├─images +│ │ Bitmap1.png +│ │ Bitmap2.png +│ │ Bitmap3.png +│ │ Bitmap4.png +│ │ Bitmap5.png +│ │ level.png +│ │ stopDemo.png +│ │ suspend.png +│ │ _preloader.gif +│ │ 任务完成_.png +│ │ 倒计时_.png +│ │ 再来一次_.png +│ │ 树林前景_.png +│ │ 计时_.png +│ │ 返回按钮_.png +│ │ +│ ├─libs +│ │ └─1.0.0 +│ │ createjs.min.js +│ │ +│ └─sounds +│ amazing.mp3 +│ bgmMusic.mp3 +│ excitationMusic.mp3 +│ unbelievable.mp3 +│ +├─public +│ │ bird.html +│ │ bird.js +│ │ index.html +│ │ 鸟妈妈回家_HTML5 Canvas.fla +│ │ +│ ├─images +│ │ Bitmap1.png +│ │ Bitmap2.png +│ │ Bitmap3.png +│ │ Bitmap4.png +│ │ Bitmap5.png +│ │ level.png +│ │ stopDemo.png +│ │ suspend.png +│ │ _preloader.gif +│ │ 任务完成_.png +│ │ 倒计时_.png +│ │ 再来一次_.png +│ │ 树林前景_.png +│ │ 计时_.png +│ │ 返回按钮_.png +│ │ +│ ├─libs +│ │ └─1.0.0 +│ │ createjs.min.js +│ │ +│ └─sounds +│ amazing.mp3 +│ bgmMusic.mp3 +│ excitationMusic.mp3 +│ unbelievable.mp3 +│ +└─src + │ custom.js + │ index.js + │ test.js + │ + └─classes + again.js + back.js + count.js + demo.js + end.js + level.js + main.js + sound.js + suspend.js + time.js +``` + +| 文件 | 说明 | 备注 | +| ------------------- | ------------------------------------------------------------ | ----------------------------------------------- | +| bird.html | animate自动生成的html,不编辑使用index.html代替 | | +| bird.js | animate自动生成,index.html有引用 | | +| images/* | animate生成的图片资源 | 这里没有使用雪碧图,这个文件fla导出雪碧图就卡死 | +| index.html | 入口界面 | | +| js/custom.js | 自定义初始化整合js | **可作为模板复制修改**,config及initStage | +| js/index.js | animate生成的内嵌到bird.html中的js提取,并添加了初始化入口函数initStage | | +| js/test.js | 测试程序,正式版可删除 | | +| js/classes/* | 封装的各个模块类 | | +| js/classes/back.js | 返回按钮类封装 | **通用** | +| js/classes/bird.js | 游戏主体类封装 | 不通用 | +| js/classes/count.js | 开始时倒计时组件类封装 | **通用**,配合custom里的配置使用 | +| js/classes/end.js | 游戏结束,得分面板 | **通用**,配合custom里的config总分,总次数使用 | +| js/classes/level.js | 游戏级别组件封装类 | **通用**,配合custom里的config里的level使用 | +| js/classes/sound.js | 游戏音频封装类 | **通用**,资源可能需要替换 | +| js/classes/time.js | 游戏时长、计时组件封装类 | **通用**,配合custom里的config里的time使用 | +| libs/* | animate导出的createjs文件 | 不用动 | +| sounds/*.mp3 | 音频资源 | | +| *.fla | animate源文件 | | + + + +## 具体代码说明 + +### index.html + +入口界面,依据animate生成的 bird.html 修改而来。主要添加了测试功能区,以及js文件的整合引入。其他不动 + +```js + + + + + + +
+ + +
+
+ +``` + +### index.js + +将原bird.html中的内嵌js部分抽离,并添加initStage调用,如下: + +```js +function handleComplete(evt, comp) { + //This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage. + var lib = comp.getLibrary(); + var ss = comp.getSpriteSheet(); + var queue = evt.target; + var ssMetadata = lib.ssMetadata; +// for循环 i=0; 前面需要加 let, 否则编译会报错 + for (i = 0; i < ssMetadata.length; i++) { + ss[ssMetadata[i].name] = new createjs.SpriteSheet({ images: [queue.getResult(ssMetadata[i].name)], frames: ssMetadata[i].frames }); + } + var preloaderDiv = document.getElementById('_preload_div_'); + preloaderDiv.style.display = 'none'; + canvas.style.display = 'block'; + exportRoot = new lib.鸟妈妈回家_HTML5Canvas(); + stage = new lib.Stage(canvas); + //Registers the "tick" event listener. + fnStartAnimation = function () { + stage.addChild(exportRoot); + + initStage(lib); + + createjs.Ticker.framerate = lib.properties.fps; + createjs.Ticker.addEventListener('tick', stage); + }; + //Code to support hidpi screens and responsive scaling. + AdobeAn.makeResponsive(true, 'both', true, 1, [canvas, preloaderDiv, anim_container, dom_overlay_container]); + AdobeAn.compositionLoaded(lib.properties.id); + fnStartAnimation(); +} + +``` + +### custom.js + +配置,全局变量 及initStage整个调用各个类,注意类的调用有先后顺序之分。图层顺序在上的后调用 + +```js +const config = { + count: 5, // 默认倒计时时长 + duration: 60, // 总时长 s + level: 1, // 游戏难度级别 + total: 100, // 总分 + times: 20, // 动作次数 +}; + +let library = null; +let state = 0; // 游戏状态 0->未开始 1->进行中 2->结束 + +function initStage(lib) { + library = lib; + + window.main = Main.of(gameOver); // 初始化鸟等 + window.timeInstance = Time.of(gameOver); // 初始化游戏时间 + // window.soundInstance = Sound.of(); // 初始化音频 + Level.of(2); // 游戏难度级别 + Back.of(); // 返回按钮 +} + +// 游戏结束 显示结束得分面板 +function gameOver() { + state = 2; + const times = main.times; + const score = parseInt((config.total / config.times) * times); + End.of(score); +} + +``` + +### 游戏模块组件类说明 + +以time.js 游戏计时模块为例: + +每个类除了自身的功能定义、调用之外, + ++ 统一添加了 *of* 静态方法,封装了 new 操作(不喜欢看到new)、调用了初始化 init 函数、并返回示例,因此调用时只需要`Time.of(...)` 就可以 ++ 如果有涉及到跟其他类的关联调用,如end方法中的 endCallback,以回调函数的形式传参使用 ++ 尽最大可能减少全局变量,外部变量的引用,保证函数的引用透明,让他纯,减少副作用,提高复用性 + +```js +/** + * 游戏时长 计时 + * @param {function} endCallback 倒计时结束的回调函数 + * @param {number} duration 游戏时长 + * @param {number} count 游戏倒计时时长 + * + * @property {number} duration 游戏时长 + * @property {number} count 游戏倒计时时长 + * @property {number} startTime 游戏开始是ms + * @property {boolean} started 游戏是否开始 + * @property {object} lib 资源库 + * @property {object} bg 时间倒计时背景 + * @property {object} text 倒计时文本 + * @property {number} timerId 定时器id + * @property {function} endCallback 结束回调函数 + */ +function Time(endCallback, duration, count) { + this.duration = duration; + this.count = count; + this.startTime = Date.now(); + + this.started = false; // 是否开始游戏 + + this.lib = library; + this.bg = null; + this.text = null; + this.timerId = null; + this.endCallback = endCallback; +} + +/** + * 静态方法 封装new init 返回实例 + * @param {function} endCallback 倒计时结束的回调函数 + * @param {number} duration 游戏时长 + * @param {number} count 游戏倒计时时长 + * @returns + */ +Time.of = function (endCallback, duration = config.duration || 60, count = config.count || 5) { + const instance = new Time(endCallback, duration, count); + instance.init(); + return instance; +}; + +// 初始化 +Time.prototype.init = function () { + this.renderBg(); + this.renderText(this.duration); +}; + +// 开始游戏 开始倒计时 +Time.prototype.start = function (startTime = Date.now()) { + this.started = true; + state = 1; + this.startTime = startTime; + this.update(); +}; + +// 开始游戏 开始倒计时 +Time.prototype.end = function () { + this.started = false; + this.timerId && clearTimeout(this.timerId); + this.timerId = null; + // 执行结束后的回调 + this.endCallback(); +}; + +// 渲染背景 +Time.prototype.renderBg = function () { + const initX = this.lib.properties.width - 100; + const initY = 80; + const instance = new this.lib.timeBg(); + instance.x = initX; + instance.y = initY; + this.bg = instance; + stage.addChild(instance); +}; + +// 渲染文本 +Time.prototype.renderText = function (time) { + const text = new createjs.Text(time, 'bold 40px Arial', '#823d16'); + text.x = this.lib.properties.width - 100; + text.y = 100; + text.textAlign = 'center'; + text.textBaseline = 'alphabetic'; + this.text = text; + stage.addChild(text); +}; + +// 更新文本 +Time.prototype.update = function () { + if (this.timerId || !this.started) return; + // const endTime = this.startTime + this.count * 1000 + this.duration * 1000; + const endTime = this.startTime + this.duration * 1000; + // console.log('endTime: ', endTime); + this.timerId = setInterval(() => { + let leftTime = Math.round((endTime - Date.now()) / 1000); + console.log('leftTime: ', leftTime); + this.text && stage.removeChild(this.text); + if (leftTime <= 0) { + leftTime = 0; + this.end(); + } + this.renderText(leftTime); + }, 1000); +}; + +``` + +**特别说明:**时间关系,还有很多需要完善的,比如上文中的endCallback就没有做类型判断。后续除了程序的健壮性优化提升之外,还须添加webpack工程化打包构建等,避免源代码暴露,代码体积、模块导入引用等都能得到好的提升