parent
							
								
									40ec4fa09a
								
							
						
					
					
						commit
						4746f34537
					
				| @ -0,0 +1,152 @@ | ||||
| let currentInputs={}; | ||||
| let handlers=[]; | ||||
| let config; | ||||
| 
 | ||||
| const toAngleMagnitude=(x, y) => { | ||||
| 	return { | ||||
| 		angle: ((Math.atan2(x, y)+2*Math.PI)%(2*Math.PI))/Math.PI, | ||||
| 		magnitude: Math.hypot(x, y) | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| const handleAngleMagnitude=(x, y, threshold=0, fn=null, clearBuffer=false) => { | ||||
| 	const {angle, magnitude}=toAngleMagnitude(x, y); | ||||
| 
 | ||||
| 	if(magnitude>threshold) { | ||||
| 		if(angle>.25 && angle <.75) inputs.right=true; | ||||
| 		else if(angle>.75 && angle<1.25) inputs.up=true; | ||||
| 		else if(angle>1.25 && angle<1.75) inputs.left=true; | ||||
| 		else inputs.down=true; | ||||
| 
 | ||||
| 		if(clearBuffer) inputs.clearBuffer=true; | ||||
| 		if(fn) fn(angle, magnitude); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| const handleCrosspad=(() => { | ||||
| 	const fn=e => | ||||
| 		handleAngleMagnitude( | ||||
| 			e.touches[0].clientX-window.innerWidth/2, | ||||
| 			e.touches[0].clientY-window.innerHeight/2, | ||||
| 			0, | ||||
| 			null, | ||||
| 			!config.touchscreen.buffer | ||||
| 		); | ||||
| 	return { | ||||
| 		touchstart: fn, | ||||
| 		touchmove: fn | ||||
| 	}; | ||||
| })(); | ||||
| 
 | ||||
| const handleKeyboard={ | ||||
| 	keydown: e => { | ||||
| 		let inputs=currentInputs; | ||||
| 		if(e.key=='ArrowUp') inputs.up=true; | ||||
| 		else if(e.key=='ArrowDown') inputs.down=true; | ||||
| 		else if(e.key=='ArrowLeft') inputs.left=true; | ||||
| 		else if(e.key=='ArrowRight') inputs.right=true; | ||||
| 
 | ||||
| 		if(!config.keyboard.buffer) inputs.clearBuffer=true; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| const handleJoystick=(() => { | ||||
| 	let center={ | ||||
| 		x: 0, | ||||
| 		y: 0 | ||||
| 	}; | ||||
| 	return { | ||||
| 		touchstart: e => { | ||||
| 			center.x=e.touches[0].clientX; | ||||
| 			center.y=e.touches[0].clientY; | ||||
| 		}, | ||||
| 		touchmove: e => | ||||
| 			handleAngleMagnitude( | ||||
| 				e.touches[0].clientX-center.x, | ||||
| 				e.touches[0].clientY-center.y, | ||||
| 				config.touchscreen.deadzone, | ||||
| 				null, | ||||
| 				!config.touchscreen.buffer | ||||
| 			) | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| const handleSwipe=(() => { | ||||
| 	let center={ | ||||
| 		x: 0, | ||||
| 		y: 0 | ||||
| 	}; | ||||
| 	let resetCenter=e => { | ||||
| 		center.x=e.touches[0].clientX; | ||||
| 		center.y=e.touches[0].clientY; | ||||
| 	}; | ||||
| 	return { | ||||
| 		touchstart: resetCenter, | ||||
| 		touchmove: e => | ||||
| 			handleAngleMagnitude( | ||||
| 				e.touches[0].clientX-center.x, | ||||
| 				e.touches[0].clientY-center.y, | ||||
| 				config.touchscreen.deadzone, | ||||
| 				() => resetCenter(e), | ||||
| 				!config.touchscreen.buffer | ||||
| 			) | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| const handleGamepads={ | ||||
| 	frame: () => { | ||||
| 		const gp=navigator.getGamepads()[0]; | ||||
| 		let inputs=currentInputs; | ||||
| 		if(!gp || !gp.axes) return; | ||||
| 
 | ||||
| 		handleAngleMagnitude( | ||||
| 			gp.axes[0], | ||||
| 			gp.axes[1], | ||||
| 			config.gamepad.deadzone, | ||||
| 			null, | ||||
| 			!config.gamepad.buffer | ||||
| 		); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| const handleEvent=(type, evt) => { | ||||
| 	for(let handler of handlers) { | ||||
| 		let fn=handler[type]; | ||||
| 		if(fn) fn(evt); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| const enableHandler=handler => { | ||||
| 	if(!handlers.includes(handler)) handlers.push(handler); | ||||
| }; | ||||
| const disableHandler=handler => { | ||||
| 	let idx=handlers.indexOf(handler); | ||||
| 	if(idx!=-1) handlers.splice(idx, 1); | ||||
| }; | ||||
| 
 | ||||
| const updateConfig=cfg => | ||||
| 	config=cfg; | ||||
| 
 | ||||
| const clear=() => | ||||
| 	Object | ||||
| 		.keys(currentInputs) | ||||
| 		.forEach(key => delete currentInputs[key]); | ||||
| 
 | ||||
| for(let type of ['keydown', 'touchstart', 'touchmove']) { | ||||
| 	window.addEventListener(type, handleEvent.bind(null, type)); | ||||
| } | ||||
| 
 | ||||
| return module.exports={ | ||||
| 	inputs: currentInputs, | ||||
| 	clear, | ||||
| 	enableHandler, disableHandler, | ||||
| 	framefn: handleEvent.bind(null, 'frame'), | ||||
| 	availableHandlers: { | ||||
| 		keyboard: handleKeyboard, | ||||
| 		gamepad: handleGamepads, | ||||
| 		touchscreenCrosspad: handleCrosspad, | ||||
| 		touchscreenJoystick: handleJoystick, | ||||
| 		touchscreenSwipe: handleSwipe | ||||
| 	}, | ||||
| 	updateConfig | ||||
| }; | ||||
| @ -0,0 +1,18 @@ | ||||
| const cache=Object.create(null); | ||||
| 
 | ||||
| const get=async filename => { | ||||
| 	if(cache[filename]) return cache[filename]; | ||||
| 	const req=await fetch('levels/'+filename); | ||||
| 	const json=await req.json(); | ||||
| 	return cache[filename]=json; | ||||
| }; | ||||
| 
 | ||||
| const clearCache=() => | ||||
| 	Object | ||||
| 		.keys(cache) | ||||
| 		.forEach(key => delete cache[key]); | ||||
| 
 | ||||
| return module.exports={ | ||||
| 	get, | ||||
| 	clearCache | ||||
| }; | ||||
					Loading…
					
					
				
		Reference in new issue