1 changed files with 314 additions and 13 deletions
@ -1,23 +1,324 @@ |
|||
# 鸟妈妈回家 |
|||
|
|||
## 游戏通用部分 |
|||
|
|||
### 头部-返回按钮 |
|||
|
|||
功能:返回主菜单 |
|||
## 游戏介绍 |
|||
|
|||
“鸟妈妈回家”游戏用于 康复训练,上肢训练 |
|||
|
|||
游戏使用Adobe Animate制作,游戏包含如下几个模块: |
|||
|
|||
+ 主体:鸟、背景(山、云朵、树木等)、成功次数(也能代表得分) |
|||
+ 开始倒计时:开始面板、倒计时文本 |
|||
+ 返回按钮 |
|||
+ 难度级别 |
|||
+ 游戏计时 |
|||
+ 结束modal:界面面板、得分文本 |
|||
+ 测试模块 |
|||
|
|||
|
|||
|
|||
该游戏源文件,使用旧版的flash软件制作,转换成animate支持的canvas模式。 |
|||
|
|||
游戏原有动画均在图层中制作。包括游戏动作成功的字数,也在动画中制作。游戏动作设计调整难度较大,次数修改成本较高。目前是固定的20次,一般情况是够用。 |
|||
|
|||
|
|||
|
|||
## 目录结构说明 |
|||
|
|||
```bash |
|||
. |
|||
├── README.md |
|||
├── bird.html |
|||
├── bird.js |
|||
├── images |
|||
│ ├── Bitmap1.png |
|||
│ ├── Bitmap2.png |
|||
│ ├── Bitmap3.png |
|||
│ ├── Bitmap4.png |
|||
│ ├── Bitmap5.png |
|||
│ ├── _preloader.gif |
|||
│ ├── level.png |
|||
│ ├── 任务完成_.png |
|||
│ ├── 倒计时_.png |
|||
│ ├── 树林前景_.png |
|||
│ ├── 计时_.png |
|||
│ └── 返回按钮_.png |
|||
├── index.html |
|||
├── js |
|||
│ ├── classes |
|||
│ │ ├── back.js |
|||
│ │ ├── bird.js |
|||
│ │ ├── count.js |
|||
│ │ ├── end.js |
|||
│ │ ├── level.js |
|||
│ │ ├── sound.js |
|||
│ │ └── time.js |
|||
│ ├── custom.js |
|||
│ ├── index.js |
|||
│ └── test.js |
|||
├── libs |
|||
│ └── 1.0.0 |
|||
│ └── createjs.min.js |
|||
├── sounds |
|||
│ ├── amazing.mp3 |
|||
│ ├── bgmMusic.mp3 |
|||
│ ├── excitationMusic.mp3 |
|||
│ └── unbelievable.mp3 |
|||
└── 鸟妈妈回家_HTML5 Canvas.fla |
|||
``` |
|||
|
|||
| 文件 | 说明 | 备注 | |
|||
| ------------------- | ------------------------------------------------------------ | ----------------------------------------------- | |
|||
| 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 |
|||
<script src="libs/1.0.0/createjs.min.js"></script> |
|||
<script src="bird.js"></script> |
|||
<script src="js/index.js"></script> |
|||
<script src="js/custom.js"></script> |
|||
<script src="js/classes/bird.js"></script> |
|||
<script src="js/classes/count.js"></script> |
|||
<script src="js/classes/back.js"></script> |
|||
<script src="js/classes/time.js"></script> |
|||
<script src="js/classes/level.js"></script> |
|||
<script src="js/classes/sound.js"></script> |
|||
<script src="js/classes/end.js"></script> |
|||
<script src="js/test.js"></script> |
|||
<!-- write your code here --> |
|||
</head> |
|||
<body onload="init();" style="margin:0px;"> |
|||
<div id="animation_container" style="background-color:rgba(255, 255, 255, 1.00); width:1280px; height:720px"> |
|||
<canvas id="canvas" width="1280" height="720" style="position: absolute; display: none; background-color:rgba(255, 255, 255, 1.00);"></canvas> |
|||
<div id="dom_overlay_container" style="pointer-events:none; overflow:hidden; width:1280px; height:720px; position: absolute; left: 0px; top: 0px; display: none;"> |
|||
</div> |
|||
</div> |
|||
<div id='_preload_div_' style='position:absolute; top:0; left:0; display: inline-block; height:720px; width: 1280px; text-align: center;'> <span style='display: inline-block; height: 100%; vertical-align: middle;'></span> <img src=images/_preloader.gif style='vertical-align: middle; max-height: 100%'/></div> |
|||
<div style="position: fixed; top: 0; left: 0; z-index: 999;padding: 20px"> |
|||
<h3>测试功能区</h3> |
|||
<button onclick="Count.of()">开始倒计时</button> |
|||
<button onclick="timeInstance.start()">开始游戏</button> |
|||
<button>结束游戏</button> |
|||
</div> |
|||
</body> |
|||
``` |
|||
|
|||
### index.js |
|||
|
|||
将原bird.html中的内嵌js部分抽离,并添加initStage调用,如下: |
|||
|
|||
```js |
|||
// 初始化返回按钮/退出游戏按钮 |
|||
function initBackBtn() { |
|||
obj.btnBack = new library.btnBack(); |
|||
obj.btnBack.x = 40; |
|||
obj.btnBack.y = 80; |
|||
obj.btnBack.scaleX = 1.3; |
|||
obj.btnBack.scaleY = 1.3; |
|||
stage.addChild(obj.btnBack); |
|||
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; 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.bird = Bird.of(gameOver); // 初始化鸟等 |
|||
window.timeInstance = Time.of(gameOver); // 初始化游戏时间 |
|||
// window.soundInstance = Sound.of(); // 初始化音频 |
|||
Level.of(2); // 游戏难度级别 |
|||
Back.of(); // 返回按钮 |
|||
} |
|||
|
|||
// 游戏结束 显示结束得分面板 |
|||
function gameOver() { |
|||
state = 2; |
|||
const times = bird.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工程化打包构建等,避免源代码暴露,代码体积、模块导入引用等都能得到好的提升 |
|||
|
Loading…
Reference in new issue