From 373885732a13b867da19b2a19518db46a0100734 Mon Sep 17 00:00:00 2001 From: Codinget Date: Tue, 24 Mar 2020 13:01:24 +0100 Subject: [PATCH] added progress bar --- mergejs.js | 3 +- public/index.html | 1 + src/js/assets.js | 79 +++++++++++++++++++++++ src/js/progress.js | 44 +++++++++++++ src/js/snek.js | 8 +-- fullreset.less => src/less/fullreset.less | 0 src/less/progressBar.less | 15 +++++ src/less/snek.less | 3 + 8 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 src/js/assets.js create mode 100644 src/js/progress.js rename fullreset.less => src/less/fullreset.less (100%) create mode 100644 src/less/progressBar.less diff --git a/mergejs.js b/mergejs.js index 821fe8d..6692b72 100644 --- a/mergejs.js +++ b/mergejs.js @@ -26,4 +26,5 @@ ${modSource} `); }); -fs.writeSync(1, outputCode.join('\n')); +fs.writeSync(1, outputCode.map(a => a.trim()).join('\n')); + diff --git a/public/index.html b/public/index.html index b6dde28..5beb735 100644 --- a/public/index.html +++ b/public/index.html @@ -6,6 +6,7 @@ +
diff --git a/src/js/assets.js b/src/js/assets.js new file mode 100644 index 0000000..c575954 --- /dev/null +++ b/src/js/assets.js @@ -0,0 +1,79 @@ +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 +}; + diff --git a/src/js/progress.js b/src/js/progress.js new file mode 100644 index 0000000..973f0bc --- /dev/null +++ b/src/js/progress.js @@ -0,0 +1,44 @@ +class ProgressBar { + constructor(taskCount) { + this.taskCount=taskCount; + this.completeCount=0; + this.updateListeneres=[]; + } + + get percent() { + return Math.floor(this.completeCount/this.taskCount*100); + } + + get ready() { + return this.completeCount==this.taskCount; + } + + addUpdateListener(fn) { + this.updateListeneres.push(fn.bind(this)); + } + addReadyListener(fn) { + this.updateListeneres.push(() => { + if(this.ready) fn.bind(this)(); + }); + } + + update() { + this.completeCount++; + this.updateListeneres.forEach(l => l(this)); + } + + draw(canvas, bgColor='red', textColor='black') { + let ctx=canvas.getContext('2d'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle=bgColor; + ctx.fillRect(0, 0, canvas.width*this.completeCount/this.taskCount, canvas.height); + ctx.fillStyle=textColor; + ctx.textAlign='center'; + ctx.textBaseline='center'; + ctx.font=`${canvas.height/2}px 'Fira Code'`; + ctx.fillText(this.percent+'%', canvas.width/2, canvas.height/2); + } +} + +return ProgressBar; + diff --git a/src/js/snek.js b/src/js/snek.js index f32c0cb..b577f14 100644 --- a/src/js/snek.js +++ b/src/js/snek.js @@ -1,4 +1,4 @@ -const Assets=require('assets'); +const assets=require('assets'); const [EMPTY, FOOD, WALL, SNAKE]=Array(4).keys(); @@ -47,7 +47,7 @@ class SnekGame { const offsetY=(this.canvas.height-cellSize*this.dimensions[1])/2; // draw our walls - const wall=Assets.get('wall'); + const wall=assets.get('wall'); for(let x=0; x { this.ctx.drawImage( fruit, diff --git a/fullreset.less b/src/less/fullreset.less similarity index 100% rename from fullreset.less rename to src/less/fullreset.less diff --git a/src/less/progressBar.less b/src/less/progressBar.less new file mode 100644 index 0000000..38c9854 --- /dev/null +++ b/src/less/progressBar.less @@ -0,0 +1,15 @@ +.progressBar { + position: fixed; + top: 50%; + left: 50%; + background: white; + box-shadow: black 0 0 2rem; + border-radius: 100vh; + transform: translate(-50%, -50%); + transition: top .5s ease-in-out; + + &.hiddenBottom { + top: 200vh; + } +} + diff --git a/src/less/snek.less b/src/less/snek.less index d24f1c5..469f7ac 100644 --- a/src/less/snek.less +++ b/src/less/snek.less @@ -79,3 +79,6 @@ h2 { p { font-size: 1.6rem; } + +// setup the progress bar +@import 'progressBar';