Image Loader and Sprite Animation Combined

by Santiago J

HTML

<canvas id="stage" width="640" height="480"></canvas>
<button onclick="_g.timerId = window.setInterval(draw, 1000 / 40);">Start</button>
<button onclick="window.clearInterval(_g.timerId)">Pause</button>
<button onclick="_g.lastT=Date.now()-Number(document.getElementById('stepSize').value);draw();">Step</button>
<input id="stepSize" type="text" value="10">ms
<div id="loadProgress">0%</div>

CSS

body {
    background-color: #ddd;
}
#stepSize {
    width: 64px;
}

JavaScript

// Img Loader
function loadImages(images, ontick) {
    if (typeof images !== "object") return null;
    var imgDir = {},
        imgLoaded = null,
        n = 0,
        len = 0,
        img, i;

    for (i in images) len++;
    if (typeof ontick === "function") {
        imgLoaded = function() {
            n++;
            ontick(n >= len ? imgDir : null, n, len);
        };
    }
    for (i in images) {
        img = imgDir[i] = new Image();
        if (imgLoaded !== null) img.onload = imgLoaded;
        img.src = images[i];
    }
    return imgDir;
}

var _g = {}; // Global handle
var b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxya0123456789-_";
// Animations
_g.anim = (function() {
    function range(a, b, s) {
        b==null&&(b=a,a=0); s=s||1;
        for(var i=a,r=[];s>0?i<b:i>b;i+=s)r.push(i);
        return r;
    }
    function range_b64str(a, b, s) {
        b==null&&(b=a,a=0); s=s||1;
        for(var i=a,r="";s>0?i<b:i>b;i+=s)r+=b64chars.charAt(i);
        return r;
    }
    var a = {};

    a.train = {};
    a.train.cols = 12;
    a.train.i = range(9,94,12);
    //a.train.i = range_b64str(9,94,12);
    a.train.period = 300;
    a.train.fpp = a.train.i.length / a.train.period; // frames per period
    a.train.w = a.train.h = 32;

    a.explosion = {};
    a.explosion.cols = 4;
    a.explosion.i = range(16).concat([15]).concat(range(15,-1,-1)).concat([0]);
    //a.explosion.i = "ABBCDEFGHIJKLMNOOPPPOONMLKJIHGFEDCBBAA";
    a.explosion.period = 680;
    a.explosion.fpp = a.explosion.i.length / a.explosion.period;
    a.explosion.w = a.explosion.h = 64;

    a.derpyFly = {};
    a.derpyFly.cols = 16;
    a.derpyFly.i = range(16);
    //a.derpyFly.i = range_b64str(16);
    a.derpyFly.period = 600;
    a.derpyFly.fpp = a.derpyFly.i.length / a.derpyFly.period;
    a.derpyFly.w = 106;
    a.derpyFly.h = 96;

    return a;
}());

// Define objects
_g.obj = {};
_g.obj.train = {
    x: 80,
    y: 80,
    w: 32,
    h: 32
};
_g.obj.explosion...