小游戏资源加载器

前面两章节,我们已经把背景动效和飞机的动效绘制出来了,现在,我们要把它们合并到一起了

不知道你有没有发现,背景图片和飞机图片都需要用到 onload 函数回调,所以我们要把公共部分拆出来然后分别判断是否加载完毕,对吧

Image 对象有一个 complete 属性用于判断图片是否加载完成

game.js

var c = wx.createCanvas();
var ctx = c.getContext('2d');

var img = wx.createImage();
var plane = wx.createImage();

var bgm = wx.createInnerAudioContext();
bgm.loop = true;

var bgCanvas = null;
var offset = 0;
var w = 0;
var h = 0;
var screenWidth = c.width;
var screenHeight = c.height;

// 上一次飞机的位置
var lasted = { x: 0, y: 0 };
// 触摸区域是否在飞机内部
var in_plane = false;


function init_bg() {
    bgCanvas = wx.createCanvas();
    bgCanvas.width = screenWidth;
    bgCanvas.height = screenHeight + h;

    var bgctx = bgCanvas.getContext('2d');

    var y = 0;
    var x = 0;

    // 底部多绘制一张图片
    while (y < screenHeight + h) {
        x = 0;
        while (x < screenWidth) {
            bgctx.drawImage(img, x, y, w, h);
            x += w;
        }
        y += h;
    }
}

function reset() {

    ctx.save();
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, c.width, c.height);
    ctx.restore();
}

function draw_copy() {
    ctx.save();
    ctx.textAlign = "center" // 居中对齐
    ctx.textBaseline = "middle" //垂直居中绘制
    ctx.fillStyle = "#aaa";
    ctx.font = "16px Arial" // 字体大小 16 像素
    ctx.fillText("简单教程,简单编程", c.width / 2, (c.height - 36))
    ctx.fillText(" © 2015-2018 www.twle.cn", c.width / 2, (c.height - 18));
    ctx.restore();
}

function animate_it() {

    reset(ctx);

    ctx.drawImage(bgCanvas, 0, offset, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight);
    ctx.drawImage(plane, 0, 0, 128, 128, lasted.x - 64, lasted.y - 64, 128, 128);
    draw_copy();

    offset++;
    if (offset % h == 0) {
        offset = 0;
    }

    requestAnimationFrame(animate_it);
}

wx.onShow(function () {
    bgm.play()
})

wx.onAudioInterruptionBegin(function () {
    // 暂停音乐
    bgm.stop();
    // 中断动画
    //cancelAnimationFrame(animate_it);
})

wx.onAudioInterruptionEnd(function () {

    bgm.play()
    // 恢复动画
    cancelAnimationFrame(animate_it);
})



wx.onTouchStart(function (e) {

    var x = e.touches[0].clientX;
    var y = e.touches[0].clientY;
    if (plane_hit(x, y)) {
        in_plane = true;
    }
});


wx.onTouchEnd(function (e) {

    if (in_plane) {
        lasted.x = e.touches[0].clientX;
        lasted.y = e.touches[0].clientY;
        in_plane = false;
    }
});

// 触摸移动事件
wx.onTouchMove(function (e) {

    if (in_plane) {
        lasted.x = e.touches[0].clientX;
        lasted.y = e.touches[0].clientY;
    }
})

function plane_hit(x, y) {
    return x > (lasted.x - 64) &&
        x < (lasted.x + 64) &&
        y > (lasted.y - 64) &&
        y < (lasted.y + 64);
}

function load() {
    if (img.complete && plane.complete) {
        w = screenWidth > img.width ? img.width : screenWidth;
        h = img.height * (w / img.width);
        lasted.x = (screenWidth - 128) / 2;
        lasted.y = screenHeight - 128;

        bgm.play()

        init_bg();
        ctx.drawImage(plane, 0, 0, 128, 128, lasted.x, lasted.y, 128, 128);
        draw_copy();
        requestAnimationFrame(animate_it);
    }
}

reset();

img.onload = function () { load(); }
plane.onload = function () { load(); }

bgm.src = 'audio/bgm.mp3'
img.src = "images/bg.jpg";
plane.src = "images/plane.png"

运行演示如下

资源加载器

但这样不是办法,如果还有更多的图片,还有其它音频资源,等等...每次都写一个 onload 那是会死人的

所以,索性,我们就来做一个资源加载器

var Resource = {
    _res: [], // [][] 资源对象数组, 0 表示资源 1  url  2 类型 3 是否加载完成
    _load: function (idx, ops) {
        var res = this._res[idx];
        if (!res[3]) {
            if (res[2] == "audio")
                this._load_audio(res[1], idx, ops)
            if (res[2] == "image")
                this._load_image(res[1], idx, ops);
        }
    },

    _load_image: function (src, i, ops) {
        var img = wx.createImage();
        var that = this;
        that._res[i][0] = img;
        img.onload = function () {
            that._res[i][3] = true;
        }
        img.src = src;
    },

    _load_audio: function (src, i, ops) {
        var audio = wx.createInnerAudioContext();

        if (ops != null) {
            for (var k in ops) {
                audio[k] = ops[k];
            }
        }

        var that = this;
        that._res[i][0] = audio;

        audio.onCanplay(function () {
            that._res[i][3] = true;
        });
        audio.src = src;
    },

    loaded: function (callback) {
        for (var i = 0; i < this._res.length; i++) {
            if (!this._res[i][3]) {
                var that = this;
                setTimeout(function () { that.loaded(callback); }, 200);
                return;
            }

        }
        callback();
    },

    add: function (src, type, id, ops) {
        this._res.push([null, src, type, false, id]);
        this._load(this._res.length-1, ops);
    },

    item: function (src) {
        for (var i = 0; i < this._res.length; i++) {
            if (this._res[i][1] == src) {
                return this._res[i][0];
            }
        }
        return null;
    }
}

范例演示如下

game.js

var Resource = {
    _res: [], // [][] 资源对象数组, 0 表示资源 1  url  2 类型 3 是否加载完成
    _load: function (idx, ops) {
        var res = this._res[idx];
        if (!res[3]) {
            if (res[2] == "audio")
                this._load_audio(res[1], idx, ops)
            if (res[2] == "image")
                this._load_image(res[1], idx, ops);
        }
    },

    _load_image: function (src, i, ops) {
        var img = wx.createImage();
        var that = this;
        that._res[i][0] = img;
        img.onload = function () {
            that._res[i][3] = true;
        }
        img.src = src;
    },

    _load_audio: function (src, i, ops) {
        var audio = wx.createInnerAudioContext();

        if (ops != null) {
            for (var k in ops) {
                audio[k] = ops[k];
            }
        }

        var that = this;
        that._res[i][0] = audio;

        audio.onCanplay(function () {
            that._res[i][3] = true;
        });
        audio.src = src;
    },

    loaded: function (callback) {
        for (var i = 0; i < this._res.length; i++) {
            if (!this._res[i][3]) {
                var that = this;
                setTimeout(function () { that.loaded(callback); }, 200);
                return;
            }

        }
        callback();
    },

    add: function (src, type, id, ops) {
        this._res.push([null, src, type, false, id]);
        this._load(this._res.length-1, ops);
    },

    item: function (src) {
        for (var i = 0; i < this._res.length; i++) {
            if (this._res[i][1] == src) {
                return this._res[i][0];
            }
        }
        return null;
    }
}

var c = wx.createCanvas();
var ctx = c.getContext('2d');

Resource.add('images/bg.jpg','image');
Resource.add('audio/bgm.mp3', 'audio');
Resource.loaded(function () {
    var bgm = Resource.item('audio/bgm.mp3');
    bgm.play();

    var bg = Resource.item('images/bg.jpg');
    console.log(bg)
});

哇,能听到声音了,也能看到图片了

使用资源加载器

废话不多说,直接组装就可以了

game.js

var Resource = {
    _res: [], // [][] 资源对象数组, 0 表示资源 1  url  2 类型 3 是否加载完成
    _load: function (idx, ops) {
        var res = this._res[idx];
        if (!res[3]) {
            if (res[2] == "audio")
                this._load_audio(res[1], idx, ops)
            if (res[2] == "image")
                this._load_image(res[1], idx, ops);
        }
    },

    _load_image: function (src, i, ops) {
        var img = wx.createImage();
        var that = this;
        that._res[i][0] = img;
        img.onload = function () {
            that._res[i][3] = true;
        }
        img.src = src;
    },

    _load_audio: function (src, i, ops) {
        var audio = wx.createInnerAudioContext();

        if (ops != null) {
            for (var k in ops) {
                audio[k] = ops[k];
            }
        }

        var that = this;
        that._res[i][0] = audio;

        audio.onCanplay(function () {
            that._res[i][3] = true;
        });
        audio.src = src;
    },

    loaded: function (callback) {
        for (var i = 0; i < this._res.length; i++) {
            if (!this._res[i][3]) {
                var that = this;
                setTimeout(function () { that.loaded(callback); }, 200);
                return;
            }

        }
        callback();
    },

    add: function (src, type, id, ops) {
        this._res.push([null, src, type, false, id]);
        this._load(this._res.length-1, ops);
    },

    item: function (src) {
        for (var i = 0; i < this._res.length; i++) {
            if (this._res[i][1] == src) {
                return this._res[i][0];
            }
        }
        return null;
    }
}

var c = wx.createCanvas();
var ctx = c.getContext('2d');

var img = wx.createImage();
var plane = wx.createImage();

var bgm = wx.createInnerAudioContext();
bgm.loop = true;

var bgCanvas = null;
var offset = 0;
var w = 0;
var h = 0;
var screenWidth = c.width;
var screenHeight = c.height;

// 上一次飞机的位置
var lasted = { x: 0, y: 0 };
// 触摸区域是否在飞机内部
var in_plane = false;


function init_bg() {
    bgCanvas = wx.createCanvas();
    bgCanvas.width = screenWidth;
    bgCanvas.height = screenHeight + h;

    var bgctx = bgCanvas.getContext('2d');

    var y = 0;
    var x = 0;

    // 底部多绘制一张图片
    while (y < screenHeight + h) {
        x = 0;
        while (x < screenWidth) {
            bgctx.drawImage(img, x, y, w, h);
            x += w;
        }
        y += h;
    }
}

function reset() {

    ctx.save();
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, c.width, c.height);
    ctx.restore();
}

function draw_copy() {
    ctx.save();
    ctx.textAlign = "center" // 居中对齐
    ctx.textBaseline = "middle" //垂直居中绘制
    ctx.fillStyle = "#aaa";
    ctx.font = "16px Arial" // 字体大小 16 像素
    ctx.fillText("简单教程,简单编程", c.width / 2, (c.height - 36))
    ctx.fillText(" © 2015-2018 www.twle.cn", c.width / 2, (c.height - 18));
    ctx.restore();
}

function animate_it() {

    reset(ctx);

    ctx.drawImage(bgCanvas, 0, offset, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight);
    ctx.drawImage(plane, 0, 0, 128, 128, lasted.x - 64, lasted.y - 64, 128, 128);
    draw_copy();

    offset++;
    if (offset % h == 0) {
        offset = 0;
    }

    requestAnimationFrame(animate_it);
}

wx.onShow(function () {
    bgm.play()
})

wx.onAudioInterruptionBegin(function () {
    // 暂停音乐
    bgm.stop();
    // 中断动画
    //cancelAnimationFrame(animate_it);
})

wx.onAudioInterruptionEnd(function () {

    bgm.play()
    // 恢复动画
    cancelAnimationFrame(animate_it);
})



wx.onTouchStart(function (e) {

    var x = e.touches[0].clientX;
    var y = e.touches[0].clientY;
    if (plane_hit(x, y)) {
        in_plane = true;
    }
});


wx.onTouchEnd(function (e) {

    if (in_plane) {
        lasted.x = e.touches[0].clientX;
        lasted.y = e.touches[0].clientY;
        in_plane = false;
    }
});

// 触摸移动事件
wx.onTouchMove(function (e) {

    if (in_plane) {
        lasted.x = e.touches[0].clientX;
        lasted.y = e.touches[0].clientY;
    }
})

function plane_hit(x, y) {
    return x > (lasted.x - 64) &&
        x < (lasted.x + 64) &&
        y > (lasted.y - 64) &&
        y < (lasted.y + 64);
}

function start() {

    w = screenWidth > img.width ? img.width : screenWidth;
    h = img.height * (w / img.width);

    lasted.x = (screenWidth - 128) / 2;
    lasted.y = screenHeight - 128;

    bgm.play()

    init_bg();
    ctx.drawImage(plane, 0, 0, 128, 128, lasted.x, lasted.y, 128, 128);
    draw_copy();
    requestAnimationFrame(animate_it);
}

reset();

Resource.add('images/bg.jpg', 'image');
Resource.add('audio/bgm.mp3', 'audio');
Resource.add('images/plane.png', 'image');

Resource.loaded(function () {
    bgm = Resource.item('audio/bgm.mp3');
    img = Resource.item('images/bg.jpg');
    plane = Resource.item('images/plane.png');
    start();
});

运行演示如下

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

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

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