小游戏打飞机分拆文件
拾遗的第一章节,我想献给我们的代码文件化,也就是重构了....
重构对于这种前后逻辑非常清晰的教程来说是非常致命的
重构了之后的每个章节,是带上所有文件一起,还是不带上所有文件一起?
或者给一个 .zip
格式的文件包,告诉你代码就在这里了 ?
但是,我觉得应该给读者们一个交代,重构一下
对了,重构要用到
ES6
的语法
1. 创建一个 common
目录
创建一个 common
目录用于存放一般公共文件
2. 创建一个资源类 Resource
首先我们要做的就是创建一个资源类 Resource
新创建一个文件 common/resource.js
内容如下
common/resource.js
export function Resource(uniq_id,type,local_path,remote_url){ // 本地存储文件地址,如果是远程 remote_url 则为空就好 this.local_path = local_path; this.remote_url = remote_url; // 远程 url // 资源类型 image | audio | video | file this.type = type; this.uniq_id = uniq_id; // 资源唯一 id this.complete = false; // 是否加载完成, this.option = {}; // 其它参数,主要用于初始化 this.obj = null; // 加载完成后的对象 }
3. 分拆资源加载器
- 创建一个文件
common/loader.js
然后把Resource
类相关的代码全部复制进去 - 当然了,改了之后类也重命名为
Loader
吧 - 再暴露出两个方法,一个是已经资源总数,另一个是还在加载中的资源数
- 然后再重构一些代码
common/loader.js
export Loader; var Loader = { _res: [], // Resource[] 资源对象数组,相关属性看上面的 Resouce _load: function (idx, ops) { var res = this._res[idx]; if (!res.complete) { if (res.type == "audio") this._load_audio(res, idx, ops) if (res.type == "image") this._load_image(res, idx, ops); } }, _load_image: function (res, i, ops) { var img = wx.createImage(); var that = this; that._res[i].obj = img; img.onload = function () { that._res[i].complete = true; } img.src = res.local_path || res.remote_url; }, _load_audio: function (res, i, ops) { var audio = wx.createInnerAudioContext(); if (ops != null) { for (var k in ops) { audio[k] = ops[k]; } } var that = this; that._res[i].obj = audio; audio.onCanplay(function () { that._res[i].obj = true; }); audio.src = res.local_path || res.remote_url;; }, loaded: function (callback) { for (var i = 0; i < this._res.length; i++) { if (!this._res[i].complete) { var that = this; setTimeout(function () { that.loaded(callback); }, 200); return; } } callback(); }, add: function (res) { this._res.push(res); this._load(this._res.length - 1, ops); }, item: function (uniq_id) { for (var i = 0; i < this._res.length; i++) { if (this._res[i].uniq_id == uniq_id) { return this._res[i].obj; } } return null; }, len:function() { return this._res.length; }, unloaded_cnt() { var i = 0; for (var i = 0; i < this._res.length; i++) { if ( ! this._res[i].complete) { i++; } } return i; } }
然后我们就是可以使用下面的公式来计算资源加载进度了
(100 - ( Loader.unloaded_cnt() * 100 ) / Loader.len() )
4. 分拆 Sprite
把 Sprite
基类放到独立的文件 sprite.js
common/sprite.js
export Sprite; function Sprite() { // 位置 this.x = 0; this.y = 0; //宽高 this.w = 0; this.h = 0; // 飞行速度 this.speed = 0; // 图片 this.img = null; // 绘图上下文 this.ctx = null; // 类型 this.kind = 0; // 原图位置 this.rx = 0; this.ry = 0; this.rw = 0; this.rh = 0; this.draw = function () { this.ctx.drawImage(this.img, this.rx, this.ry, this.rw, this.rh, this.x - this.w / 2, this.y - this.h / 2, this.w, this.h); } }
5. 分拆 Bucket
分拆 Bucket 到一个独立的文件 common/bucket.js
但要把 enemy_hit()
先去掉,我们在子类里添加
common/bucket.js
export Bucket; var Bucket = { _bucket: {}, move: function () { for (var i in this._bucket) { for (var j in this._bucket[i]) { this._bucket[i][j].move(); if (this._bucket[i][j].hit()) { this._bucket[i].splice(j, 1); } } } }, add: function (obj, bucket) { if (!(bucket in this._bucket)) { this._bucket[bucket] = []; } this._bucket[bucket].push(obj); }, draw: function (ctx) { for (var i in this._bucket) { for (var j in this._bucket[i]) { this._bucket[i][j].draw(); } } } }
好了,到目前为止,公共类已经分拆完毕了
6. 创建一个 game
目录
创建一个 game
目录用于当前游戏的所有脚本
7. 分拆子弹类 Bullet
分拆 Bullet
到新的文件 game/bullet.js
game/bullet.js
import Sprite from 'common/sprite.js';
小游戏开发到这里,已经能基本匹配官方的 demo 了,还差那么几个点
- 子弹发射音效
- 敌机命中音效
- 游戏开始和游戏结束
- 计分
- 排行榜
其实后面这些,都是很容易添加的,我们就不继续在写下去了,部分章节,我会以 拾遗 的方式出现
大家可以看到,一路走来,我们的代码乱乱的....为什么呢?
其实大家一开始写的时候几乎都是乱乱的,都是写到一半半的时候发现之前写的太乱然后重构下
但是,教程是不能这么做的,你不能把已经发出去的教程重新写一下,然后告诉读者们,我为什么要这么重构?
因为我后面发现逻辑是这样的?
希望这份小游戏小教程,能够带你入门....