parent
9db9b742fa
commit
39e761d334
@ -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