added progress bar
This commit is contained in:
		
							parent
							
								
									bd6d9f3399
								
							
						
					
					
						commit
						daef55781e
					
				
					 8 changed files with 148 additions and 5 deletions
				
			
		| 
						 | 
					@ -26,4 +26,5 @@ ${modSource}
 | 
				
			||||||
		`);
 | 
							`);
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fs.writeSync(1, outputCode.join('\n'));
 | 
					fs.writeSync(1, outputCode.map(a => a.trim()).join('\n'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
		<link rel="favicon" href="favicon.ico">
 | 
							<link rel="favicon" href="favicon.ico">
 | 
				
			||||||
		<link rel="stylesheet" href="css/snek.css">
 | 
							<link rel="stylesheet" href="css/snek.css">
 | 
				
			||||||
		<script src="js/snek.js"></script>
 | 
							<script src="js/snek.js"></script>
 | 
				
			||||||
 | 
							<script>window.addEventListener('load', () => require('assets'));</script>
 | 
				
			||||||
	</head>
 | 
						</head>
 | 
				
			||||||
	<body>
 | 
						<body>
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										79
									
								
								src/js/assets.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/js/assets.js
									
										
									
									
									
										Normal 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
									
								
							
							
						
						
									
										44
									
								
								src/js/progress.js
									
										
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
const Assets=require('assets');
 | 
					const assets=require('assets');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const [EMPTY, FOOD, WALL, SNAKE]=Array(4).keys();
 | 
					const [EMPTY, FOOD, WALL, SNAKE]=Array(4).keys();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ class SnekGame {
 | 
				
			||||||
		const offsetY=(this.canvas.height-cellSize*this.dimensions[1])/2;
 | 
							const offsetY=(this.canvas.height-cellSize*this.dimensions[1])/2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// draw our walls
 | 
							// draw our walls
 | 
				
			||||||
		const wall=Assets.get('wall');
 | 
							const wall=assets.get('wall');
 | 
				
			||||||
		for(let x=0; x<this.dimensions[0]; x++) {
 | 
							for(let x=0; x<this.dimensions[0]; x++) {
 | 
				
			||||||
			for(let y=0; x<this.dimensions[1]; y++) {
 | 
								for(let y=0; x<this.dimensions[1]; y++) {
 | 
				
			||||||
				switch(this.world[x][y]) {
 | 
									switch(this.world[x][y]) {
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,7 @@ class SnekGame {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// draw our snake
 | 
							// draw our snake
 | 
				
			||||||
		const snake=Assets.get('snake');
 | 
							const snake=assets.get('snake');
 | 
				
			||||||
		this.ctx.fillStyle=snake.color;
 | 
							this.ctx.fillStyle=snake.color;
 | 
				
			||||||
		this.ctx.strokeStyle=snake.color;
 | 
							this.ctx.strokeStyle=snake.color;
 | 
				
			||||||
		this.ctx.lineCap=snake.cap;
 | 
							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
 | 
							// our fruit has a nice animation to it between .8 and 1.2 scale
 | 
				
			||||||
		const ms=Date.now();
 | 
							const ms=Date.now();
 | 
				
			||||||
		const fruitScale=Math.sin(ms/1000*Math.PI)*.2+1
 | 
							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.fruits.forEach(([x, y]) => {
 | 
				
			||||||
			this.ctx.drawImage(
 | 
								this.ctx.drawImage(
 | 
				
			||||||
				fruit,
 | 
									fruit,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/less/progressBar.less
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/less/progressBar.less
									
										
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,3 +79,6 @@ h2 {
 | 
				
			||||||
p {
 | 
					p {
 | 
				
			||||||
	font-size: 1.6rem;
 | 
						font-size: 1.6rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// setup the progress bar
 | 
				
			||||||
 | 
					@import 'progressBar';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue