UNPKG

pixelbox

Version:

A framework to fast-prototype pixel-based games

189 lines (175 loc) 6.32 kB
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ /** * @module assetLoader * @desc Loading functions helpers * * @author Cedric Stoquer */ function loadData(path, responseType, cb) { var xobj = new XMLHttpRequest(); xobj.responseType = responseType || 'arraybuffer'; xobj.onreadystatechange = function onXhrStateChange() { if (~~xobj.readyState !== 4) return; if (~~xobj.status !== 200 && ~~xobj.status !== 0) { return cb && cb('xhrError:' + xobj.status); } return cb && cb(null, xobj.response); }; xobj.open('GET', path, true); xobj.send(); } exports.loadData = loadData; //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ /** * @function module:loader.loadJson * @desc load a json file * * @param {String} path - file path * @param {Function} cb - asynchronous callback function */ function loadJson(path, cb) { var xobj = new XMLHttpRequest(); xobj.onreadystatechange = function () { if (~~xobj.readyState !== 4) return; if (~~xobj.status !== 200) return cb('xhrError:' + xobj.status); return cb && cb(null, JSON.parse(xobj.response)); }; xobj.open('GET', path, true); xobj.send(); } exports.loadJson = loadJson; //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ /** * @function module:loader.loadImage * @desc load an image file * * @param {String} path - file path * @param {Function} cb - asynchronous callback function */ function loadImage(path, cb) { var img = new Image(); // TODO: remove listeners when load / error img.onload = function () { this.onload = null; this.onerror = null; cb && cb(null, this); }; img.onerror = function () { this.onload = null; this.onerror = null; cb && cb('img:' + path); }; img.src = path; } exports.loadImage = loadImage; //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ /** * @function module:loader.loadSound * @desc load an image file * * @param {String} path - file path * @param {Function} cb - asynchronous callback function */ function loadSound(path, cb) { var snd = new Audio(); snd.preload = true; snd.loop = false; function onSoundLoad() { cb && cb(null, snd); snd.removeEventListener('canplaythrough', onSoundLoad); snd.removeEventListener('error', onSoundError); } function onSoundError() { cb && cb('snd:load'); snd.removeEventListener('canplaythrough', onSoundLoad); snd.removeEventListener('error', onSoundError); } snd.addEventListener('canplaythrough', onSoundLoad); snd.addEventListener('error', onSoundError); snd.src = path; snd.load(); } exports.loadSound = loadSound; //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ /** * @function module:loader.preloadStaticAssets * * @desc Preload all static assets of the game. * The function first ask the server for the asset list. * Server respond with an object containing the list of images * to load and all data that are put in the www/asset folder. * At this step, if request fail, function send an error. * The function then proceed the loading of image assets. * If an image loading fail, the loading continue, and loading * status is set to 1 (an image load fail). * Images are load by 5 in parallel. * * Function end and wil return an object that mix all data and * all assets so that it will have the same structure as the * 'assets' folder. * * * Assets list and data are automaticaly generated by server * Just drop images and json files in the www/asset/ folder * and the server will take care of it ! * * * @param {Function} cb - asynchronous callback function to * call when all is preloaded * * @param {Function} onEachLoad - optional callback function called * every time one file is loaded * (for loading progress purpose) * */ function preloadStaticAssets(assetList, cb, onEachLoad) { var data = assetList.dat; var imgCount = assetList.img.length; var count = imgCount + assetList.snd.length; var root = assetList.root; var load = 0; var done = 0; function storeAsset(path, obj) { var splitted = path.split('/'); var filename = splitted.pop(); var id = filename.split('.'); id.pop(); id = id.join('.'); var container = data; for (var i = 0, len = splitted.length; i < len; i++) { container = container[splitted[i]]; } container[id] = obj; splitted.push(id); obj.name = id; obj.path = splitted.join('/'); } function loadAssets() { var current = load + done; var percent = current / count; onEachLoad && onEachLoad(load, current, count, percent); var path; var loadFunc; if (current < imgCount) { path = assetList.img[current]; loadFunc = loadImage; } else { path = assetList.snd[current - imgCount]; loadFunc = loadSound; } done += 1; loadFunc(root + path, function onAssetLoaded(error, img) { if (!error) storeAsset(path, img); load += 1; done -= 1; if (load + done < count) loadAssets() else if (done === 0) cb(null, data); }); } // loading assets in parallel, with a limit of 5 parallel downloads. if (count === 0) return cb(null, data); var parallel = Math.min(5, count - 1); for (var j = 0; j <= parallel; j++) loadAssets(); // }); } exports.preloadStaticAssets = preloadStaticAssets;