added progress bar

This commit is contained in:
Nathan DECHER 2020-03-24 13:01:24 +01:00
parent bd6d9f3399
commit daef55781e
8 changed files with 148 additions and 5 deletions

View file

@ -26,4 +26,5 @@ ${modSource}
`);
});
fs.writeSync(1, outputCode.join('\n'));
fs.writeSync(1, outputCode.map(a => a.trim()).join('\n'));

View file

@ -6,6 +6,7 @@
<link rel="favicon" href="favicon.ico">
<link rel="stylesheet" href="css/snek.css">
<script src="js/snek.js"></script>
<script>window.addEventListener('load', () => require('assets'));</script>
</head>
<body>
<header>

79
src/js/assets.js Normal file
View file

@ -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
};

44
src/js/progress.js Normal file
View file

@ -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;

View file

@ -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.dimensions[0]; x++) {
for(let y=0; x<this.dimensions[1]; y++) {
switch(this.world[x][y]) {
@ -65,7 +65,7 @@ class SnekGame {
}
// draw our snake
const snake=Assets.get('snake');
const snake=assets.get('snake');
this.ctx.fillStyle=snake.color;
this.ctx.strokeStyle=snake.color;
this.ctx.lineCap=snake.cap;
@ -96,7 +96,7 @@ class SnekGame {
// our fruit has a nice animation to it between .8 and 1.2 scale
const ms=Date.now();
const fruitScale=Math.sin(ms/1000*Math.PI)*.2+1
const fruit=Assets.get('fruit');
const fruit=assets.get('fruit');
this.fruits.forEach(([x, y]) => {
this.ctx.drawImage(
fruit,

15
src/less/progressBar.less Normal file
View file

@ -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;
}
}

View file

@ -79,3 +79,6 @@ h2 {
p {
font-size: 1.6rem;
}
// setup the progress bar
@import 'progressBar';