const ProgressBar=require('progress'); const assetSpecs=[ { name: 'fruit', filename: 'apple32.png', type: 'image' }, { name: 'wall', filename: 'wall32.png', type: 'image' }, { name: 'snake', filename: 'snake.json', type: 'json' } ]; const cvs=document.createElement('canvas'); cvs.width=400; cvs.height=50; cvs.classList.add('progressBar'); cvs.classList.add('hiddenBottom'); const bar=new ProgressBar(assetSpecs.length*2); bar.addUpdateListener(() => bar.draw(cvs)); bar.draw(cvs); document.body.appendChild(cvs); setTimeout(() => cvs.classList.remove('hiddenBottom'), 0); bar.addReadyListener(() => { cvs.classList.add('hiddenBottom'); setTimeout(() => document.body.removeChild(cvs), 1000); }); //XXX purposefully slow down asset loading const sleep=(ms) => new Promise(ok => setTimeout(ok, ms)); const loadAsset=async (asset) => { const response=await fetch('assets/'+asset.filename); await sleep(1000*Math.random()); bar.update(); let result; switch(asset.type) { case 'json': result=await response.json(); break; case 'image': result=await createImageBitmap(await response.blob()); break; } await sleep(1000*Math.random()); bar.update(); return [asset.name, result]; }; let assets=Object.create(null); let ready=false; let readyListeners=[]; Promise .all( assetSpecs.map(a => loadAsset(a)) ).then(arr => { arr.forEach(([name, value]) => { assets[name]=value; }); ready=true; readyListeners.forEach(fn => fn.bind(fn)()); readyListeners=null; }); const onReady=(fn) => { if(ready) fn.bind(fn)(); else readyListeners.push(ready); }; const get=(name) => { let asset=assets[name]; if(!asset) throw new Error("Unknown asset: "+name); return asset; }; return { onReady, get };