|  |  |  | @ -117,15 +117,8 @@ class SnekGame { | 
			
		
	
		
			
				
					|  |  |  |  | 		const offsetX=(this.canvas.width-cellSize*this.dimensions[0])/2; | 
			
		
	
		
			
				
					|  |  |  |  | 		const offsetY=(this.canvas.height-cellSize*this.dimensions[1])/2; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// draw the border around our game area
 | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillStyle='black'; | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillRect(0, 0, this.canvas.width, offsetY); | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillRect(0, 0, offsetX, this.canvas.height); | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillRect(offsetX+cellSize*this.dimensions[0], 0, offsetX, this.canvas.height); | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillRect(0, offsetY+cellSize*this.dimensions[1], this.canvas.width, offsetY); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// draw a grid/checkerboard if requested
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if(config.get('appearance.grid')=='grid') { | 
			
		
	
		
			
				
					|  |  |  |  | 		if(config.getS('appearance.grid')=='grid') { | 
			
		
	
		
			
				
					|  |  |  |  | 			this.ctx.strokeStyle='rgba(0, 0, 0, 50%)'; | 
			
		
	
		
			
				
					|  |  |  |  | 			this.ctx.lineCap='square'; | 
			
		
	
		
			
				
					|  |  |  |  | 			this.ctx.lineWidth=1; | 
			
		
	
	
		
			
				
					|  |  |  | @ -139,7 +132,7 @@ class SnekGame { | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.lineTo(this.canvas.width-offsetX, offsetY+y*cellSize); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			this.ctx.stroke(); | 
			
		
	
		
			
				
					|  |  |  |  | 		} else if(config.get('appearance.grid')=='checkerboard') { | 
			
		
	
		
			
				
					|  |  |  |  | 		} else if(config.getS('appearance.grid')=='checkerboard') { | 
			
		
	
		
			
				
					|  |  |  |  | 			this.ctx.fillStyle='rgba(0, 0, 0, 10%)'; | 
			
		
	
		
			
				
					|  |  |  |  | 			for(let x=0; x<this.dimensions[0]; x++) { | 
			
		
	
		
			
				
					|  |  |  |  | 				for(let y=(x+1)%2; y<this.dimensions[1]; y+=2) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -254,6 +247,69 @@ class SnekGame { | 
			
		
	
		
			
				
					|  |  |  |  | 				cellSize*fruitScale | 
			
		
	
		
			
				
					|  |  |  |  | 			); | 
			
		
	
		
			
				
					|  |  |  |  | 		}); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// show the timer
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if(this.rules.winCondition=='time') { | 
			
		
	
		
			
				
					|  |  |  |  | 			if(config.getS('appearance.timer')=='border' || config.getS('appearance.timer')=='both') { | 
			
		
	
		
			
				
					|  |  |  |  | 				let remaining=(this.rules.gameDuration-this.playTime)/this.rules.gameDuration; | 
			
		
	
		
			
				
					|  |  |  |  | 				const w=this.dimensions[0]*cellSize; | 
			
		
	
		
			
				
					|  |  |  |  | 				const h=this.dimensions[1]*cellSize; | 
			
		
	
		
			
				
					|  |  |  |  | 				const p=w*2+h*2; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				const wp=w/p; | 
			
		
	
		
			
				
					|  |  |  |  | 				const hp=h/p; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				const pdst=(st, ed, frac) => | 
			
		
	
		
			
				
					|  |  |  |  | 					(ed-st)*frac+st; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.strokeStyle='#930a16'; | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.lineJoin='miter'; | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.lineCap='round'; | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.lineWidth=5; | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.beginPath(); | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.moveTo(this.canvas.width/2, offsetY+2); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				let sp=Math.min(wp/2, remaining); | 
			
		
	
		
			
				
					|  |  |  |  | 				remaining-=sp; | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.lineTo(pdst(this.canvas.width/2, w+offsetX-2, sp/wp*2), offsetY+2); | 
			
		
	
		
			
				
					|  |  |  |  | 				if(remaining) { | 
			
		
	
		
			
				
					|  |  |  |  | 					sp=Math.min(hp, remaining); | 
			
		
	
		
			
				
					|  |  |  |  | 					remaining-=sp; | 
			
		
	
		
			
				
					|  |  |  |  | 					this.ctx.lineTo(w+offsetX-2, pdst(offsetY+2, offsetY+h-2, sp/hp)); | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 				if(remaining) { | 
			
		
	
		
			
				
					|  |  |  |  | 					sp=Math.min(wp, remaining); | 
			
		
	
		
			
				
					|  |  |  |  | 					remaining-=sp; | 
			
		
	
		
			
				
					|  |  |  |  | 					this.ctx.lineTo(pdst(w+offsetX-2, offsetX+2, sp/wp), offsetY+h-2); | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 				if(remaining) { | 
			
		
	
		
			
				
					|  |  |  |  | 					sp=Math.min(hp, remaining); | 
			
		
	
		
			
				
					|  |  |  |  | 					remaining-=sp; | 
			
		
	
		
			
				
					|  |  |  |  | 					this.ctx.lineTo(offsetX+2, pdst(offsetY+h-2, offsetY+2, sp/hp)); | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 				if(remaining) { | 
			
		
	
		
			
				
					|  |  |  |  | 					this.ctx.lineTo(pdst(offsetX+2, this.canvas.width/2, remaining/wp*2), offsetY+2); | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.stroke(); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			if(config.getS('appearance.timer')=='number' || config.getS('appearance.timer')=='both') { | 
			
		
	
		
			
				
					|  |  |  |  | 				let remaining=''+Math.ceil((this.rules.gameDuration-this.playTime)/1000); | 
			
		
	
		
			
				
					|  |  |  |  | 				while(remaining.length<(''+this.rules.gameDuration/1000).length) remaining='0'+remaining; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.fillStyle='#930a16'; | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.textAlign='center'; | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.textBaseline='middle'; | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.font='4rem "Fira Code"'; | 
			
		
	
		
			
				
					|  |  |  |  | 				this.ctx.fillText(remaining, this.canvas.width/2, this.canvas.height/2); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// draw the border around our game area
 | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillStyle='black'; | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillRect(0, 0, this.canvas.width, offsetY); | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillRect(0, 0, offsetX, this.canvas.height); | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillRect(offsetX+cellSize*this.dimensions[0], 0, offsetX, this.canvas.height); | 
			
		
	
		
			
				
					|  |  |  |  | 		this.ctx.fillRect(0, offsetY+cellSize*this.dimensions[1], this.canvas.width, offsetY); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	step() { | 
			
		
	
	
		
			
				
					|  |  |  | 
 |