小游戏打飞机分拆文件

拾遗的第一章节,我想献给我们的代码文件化,也就是重构了....

重构对于这种前后逻辑非常清晰的教程来说是非常致命的

重构了之后的每个章节,是带上所有文件一起,还是不带上所有文件一起?

或者给一个 .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. 分拆资源加载器

  1. 创建一个文件 common/loader.js 然后把 Resource 类相关的代码全部复制进去
  2. 当然了,改了之后类也重命名为 Loader
  3. 再暴露出两个方法,一个是已经资源总数,另一个是还在加载中的资源数
  4. 然后再重构一些代码

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 了,还差那么几个点

  1. 子弹发射音效
  2. 敌机命中音效
  3. 游戏开始和游戏结束
  4. 计分
  5. 排行榜

其实后面这些,都是很容易添加的,我们就不继续在写下去了,部分章节,我会以 拾遗 的方式出现

大家可以看到,一路走来,我们的代码乱乱的....为什么呢?

其实大家一开始写的时候几乎都是乱乱的,都是写到一半半的时候发现之前写的太乱然后重构下

但是,教程是不能这么做的,你不能把已经发出去的教程重新写一下,然后告诉读者们,我为什么要这么重构?

因为我后面发现逻辑是这样的?

希望这份小游戏小教程,能够带你入门....

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.