var MAX_CONTROLLER = 4; var gamepadReady = 0; var gamepadPollingId = null; var gamepadLastId = -1; //for send to server only var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; var cancelRequestAnimationFrame = window.cancelRequestAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame; function gamepadEnable() { if(!gamepadSupport()) return; window.addEventListener("gamepadconnected",gamepadConnectFun, false); window.addEventListener("gamepaddisconnected", gamepadDisconnectFun, false); gamepadPollingId = setInterval(gamepadCheck, 500); } function gamepadSupport() { return ("getGamepads" in navigator) || ("webkitGetGamepads" in navigator); } function gamepadConnectFun(e) { //console.log("Gamepad connected at index %d: %s. %d buttons, %d axes.", // e.gamepad.index, e.gamepad.id, // e.gamepad.buttons.length, e.gamepad.axes.length); gamepadReady = 1; if(gamepadPollingId) { clearInterval(gamepadPollingId); gamepadPollingId = null; } requestAnimationFrame(gamepadRequestState); } function gamepadDisconnectFun(e) { console.log("disconnection game port#%d", e.gamepad.index ); gamepadReady = 0; if(!gamepadPollingId) gamepadPollingId = setInterval(gamepadCheck, 500); } function gamepadCheck() { gamepad = gamepadGetInstance(); for(var id=0; id < MAX_CONTROLLER; id ++) { if(gamepad[id]) { if(!gamepadReady) { gamepadConnectTrigger(gamepad[id]); } } } } function gamepadGetInstance() { return ("getGamepads" in navigator) ? navigator.getGamepads() : (("webkitGetGamepads" in navigator) ? navigator.webkitGetGamepads() : []); } //================================= // Generate gamepadconnected event //================================= function gamepadConnectTrigger(gamepad) { var event = document.createEvent('Event'); event.initEvent("gamepadconnected", true, true); //can bubble, and is cancellable event.gamepad = gamepad; dispatchEvent(event); } function gamepadDisable() { if(!gamepadSupport()) return; window.removeEventListener("gamepadconnected",gamepadConnectFun, false); window.removeEventListener("gamepaddisconnected", gamepadDisconnectFun, false); if(gamepadPollingId) { clearInterval(gamepadPollingId); gamepadPollingId = null; } gamepadReady = 0; } function getLastGamepadInfo() { var gamepadInfo = null; if(gamepadLastId >= 0 && gamepadLastId < MAX_CONTROLLER ) { var gamepad = gamepadGetInstance()[gamepadLastId]; if(gamepad) { gamepadInfo =gamepad.index + "." + gamepad.id + (gamepad.mapping != ""?("." +gamepad.mapping):""); } } return gamepadInfo; } //=========================================================================== var keyCodeMapping = [ //[[keyCode1, ctrl, shift], [keyCode2, ctrl, shift] [["ArrowUp", 0, 0], ["ArrowUp", 0, 0]], //up [["ArrowDown", 0, 0], ["ArrowDown", 0, 0]], //down [["ArrowLeft", 0, 0], ["ArrowLeft", 0, 0]], //left [["ArrowRight", 0, 0], ["ArrowRight", 0, 0]], //right [["KeyZ", 0, 0], ["Enter", 0, 0]], //dig-left [["KeyX", 0, 0], ["Enter", 0, 0]], //dig-right [["Escape", 0, 0], ["Enter", 0, 0]], //pause [["Enter", 0, 0], ["Enter", 0, 0]], //enter [["KeyA", 1, 0], ["Enter", 0, 0]] //game abort ]; var gameButtonMapping = [ //index[0] buttonMethod: 0: don't repeat, 1: repeat, 2: combine button [ 1, ['B', 12],['A', 1, "<", -0.6],['B', 16]], //UP [ 1, ['B', 13],['A', 1, ">", 0.6],['B', 17]], //DOWN [ 1, ['B', 14],['A', 0, "<", -0.6],['B', 18]], //LEFT [ 1, ['B', 15],['A', 0, ">", 0.6],['B', 19]], //RIGHT [ 1, ['B', 2],['B', 3]], //DIG-LEFT [ 1, ['B', 1]], //DIG-RIGHT [ 0, ['B', 8],['B', 11]], //PAUSE (ESC) [ 0, ['B', 9]], //Enter (Accept) [ 2, ['B', 4],['B', 5], ['B', 6],['B', 7]] //GAME ABORT (CTRL-A) ]; var lastButtonState = [ [ 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0] ]; function gamepadRequestState() { var i, j; var gamepad, curButtonState; var buttonMethod; for(var id=0; id < MAX_CONTROLLER; id ++) { gamepad = gamepadGetInstance()[id]; curButtonState = []; if(gamepad) { for(i = 0; i < gameButtonMapping.length; i++) { curButtonState[i] = 0; buttonMethod = gameButtonMapping[i][0]; for(j = 1; j < gameButtonMapping[i].length && !curButtonState[i]; j++) { var curButtonMapping = gameButtonMapping[i][j]; switch(curButtonMapping[0]) { case 'A': //axes var axesId = curButtonMapping[1]; if(gamepad.axes.length > axesId) { var axesCmpSign = curButtonMapping[2]; var axesCmpValue = curButtonMapping[3]; var axesValue = Math.trunc(gamepad.axes[axesId]*100)/100; if(typeof axesValue != 'undefined' ) { if( (axesCmpSign == ">" && axesValue > axesCmpValue && axesValue <= 1.05) ||(axesCmpSign == "<" && axesValue < axesCmpValue && axesValue >= -1.05) ) { //console.log("axes#%d = %f", axesId, axesValue ); curButtonState[i] = 1; } } } break; case 'B': //button var buttonId = curButtonMapping[1]; var button = gamepad.buttons[buttonId]; if(buttonPressed(button)) curButtonState[i] = 1; if(buttonMethod == 2) { //combine mode j++; if(curButtonState[i]) { curButtonMapping = gameButtonMapping[i][j]; buttonId = curButtonMapping[1]; button = gamepad.buttons[buttonId]; if(buttonPressed(button)) { curButtonState[i] = 1; } else { curButtonState[i] = 0; } } } break; } } switch(buttonMethod) { case 1: //repeat if(document.onkeydown == handleKeyDown || document.onkeydown == anyKeyDown) { if(curButtonState[i])sendKeyDown(keyCodeMapping[i], id); else if(lastButtonState[id][i]) sendKeyUp(keyCodeMapping[i], id); break; } case 0: //don't repeat case 2: if(lastButtonState[id][i] != curButtonState[i]) { if(curButtonState[i])sendKeyDown(keyCodeMapping[i], id); else if(lastButtonState[id][i]) sendKeyUp(keyCodeMapping[i], id); } break; } } lastButtonState[id] = curButtonState; } } if(gamepadReady) requestAnimationFrame(gamepadRequestState); } function buttonPressed(button) { var pressed = button == 1.0; if (typeof(button) == "object") { pressed = button.pressed; } return pressed; } function gamepadClearId() { gamepadLastId = -1; } function sendKeyUp(twinKey, id) { var key = (inputNameState)? twinKey[1]:twinKey[0]; if(key[0] == null) return; var event = {code: key[0], ctrlKey: key[1], shiftKey: key[2]}; //console.log("sendKeyUp = %d",keyCode ); if(typeof document.onkeydown == "function" ) document.onkeyup(event); gamepadLastId = id; } function sendKeyDown(twinKey, id) { var key = (inputNameState)? twinKey[1]:twinKey[0]; if(key[0] == null) return; var event = {code: key[0], ctrlKey: key[1], shiftKey: key[2]}; //console.log("sendKeyDown = %d",keyCode ); if(typeof document.onkeydown == "function" ) document.onkeydown(event); gamepadLastId = id; }