Open AlexZ33 opened 1 year ago
let AXIS_LXLY = 2007, //左摇杆标识 AXIS_RXRY = 2008, //右摇杆标识 AXIS_LT = 2009, //LT杆标识 AXIS_RT = 2010, //RT杆标识 KEY_DOWN = 2011, // 按键按下 KEY_UP = 2012; // 按键抬起 let gamepadconnected, gamepaddisconnected; let gamepadControl = () => { let hadleStart = null, controllers = {}, // 手柄控制信息,是个对象 handleStatus = [], // 准备更新动画时调用此方法 rAF = window.mozRequestAnimationFrame || window.requestAnimationFrame, // 取消先前通过 requestAnimationFrame 添加到计划中的动画帧请求 rAFStop = window.mozCancelAnimationFrame || window.cancelAnimationFrame, notStandardMap = {}; const getGamepadsCompatible = () => navigator.getGamepads ? navigator.getGamepads() : navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []; gamepadconnected = () => { WelinkGamePadLoop(); }; gamepaddisconnected = (e) => { const noGamepads = getGamepadsCompatible().every(o => o === null); if (noGamepads) { rAFStop(hadleStart); } delete notStandardMap[e.gamepad.index]; } // 监听手柄连接 // 实测发现,只在第一次连接/第一次按下手柄按键时有用 window.addEventListener('gamepadconnected', gamepadconnected); // 监听手柄断开 window.addEventListener('gamepaddisconnected', gamepaddisconnected); // 扫描全部手柄信息 let WelinkScanGamepads = () => { let gamepads = getGamepadsCompatible(); if (!gamepads) return; for (let i = 0; i < gamepads.length; i++) { if (gamepads[i]) { const index = gamepads[i].index; if (gamepads[i].mapping !== 'standard') { if (!notStandardMap[index]) { notStandardMap[index] = 1; console.warn(`手柄 '${index}' 按键映射是不标准的,无法使用`); } break; } else { delete notStandardMap[index]; } controllers[index] = gamepads[i]; } } }; // 物理手柄状态 let WelinkGamePadLoop = () => { // 开启扫描 WelinkScanGamepads(); // 解析手柄 WelinkhandleShank(controllers); hadleStart = null; hadleStart = rAF(WelinkGamePadLoop); }; // 解析实体手柄 let WelinkhandleShank = (data) => { for (let j in data) { let thisStatus = { buttons: [], axes: [] }, handle = data[j], handModel = handle.id.toLowerCase(); // 遍历按键 for (let i = 0; i < handle.buttons.length; i++) { let btn = handle.buttons[i], status = btn.touched ? 1 : 0, conf = [4096, 8192, 16384, 32768, 256, 512, 255, 255, 32, 16, 64, 128, 1, 2, 4, 8, 0], type = ''; if (handModel.indexOf('wireless controller') != -1) { // ps4应该是18个 conf = [4096, 8192, 16384, 32768, 256, 512, 255, 255, 32, 16, 64, 128, 1, 2, 4, 8, 0, 0]; } type = i == 6 ? 'OP_XINPUT_LEFT_TRIGGER' : i == 7 ? 'OP_XINPUT_RIGHT_TRIGGER' : 'OP_XINPUT_BUTTONS'; if (handleStatus && handleStatus[j]) { // 有记录的处理 if (handleStatus[j].buttons[i] != status) { if (btn.touched) { WelinkSendHald(conf[i], type, j, conf[i]); } else { WelinkSendHald(0, type, j, conf[i]); } } } else { // 无记录的 if (btn.touched) { WelinkSendHald(conf[i], type, j, conf[i]); } } thisStatus.buttons[i] = status; } // 处理摇杆 let rocker = handle.axes, LX = Math.round(rocker[0] * 32767), LY = Math.round(rocker[1] * -32767), RX = Math.round(rocker[2] * 32767), RY = 0, CR = 0; // 判断是否Xbox360模式 if (handModel.indexOf('360') != -1 || handModel.indexOf('xbox') != -1 || handModel.indexOf('wireless controller') != -1) { // Xbox360模式键位 RY = Math.round(rocker[3] * -32767); CR = 0; } else { //安卓模式键位 RY = Math.round(rocker[5] * -32767); // 处理十字键 CR = Math.round(rocker[9] * 1000); } if (handleStatus && handleStatus[j]) { // 有记录的处理 if (handleStatus[j].axes[0] != LX) { WelinkSendHald(LX, 'OP_XINPUT_THUMB_LX', j); } if (handleStatus[j].axes[1] != LY) { WelinkSendHald(LY, 'OP_XINPUT_THUMB_LY', j); } if (handleStatus[j].axes[2] != RX) { WelinkSendHald(RX, 'OP_XINPUT_THUMB_RX', j); } if (handleStatus[j].axes[3] != RY) { WelinkSendHald(RY, 'OP_XINPUT_THUMB_RY', j); } if ((handModel.indexOf('360') == -1 && handModel.indexOf('xbox') == -1) || handModel.indexOf('wireless controller') != -1) { // 处理安卓模式十字键 if (handleStatus[j].axes[4] != CR) { // 判断是否按下 if (CR <= 1000) { if (CR == 714) { WelinkSendHald(4, 'OP_XINPUT_BUTTONS', j, 4); } else if (CR == 143) { WelinkSendHald(2, 'OP_XINPUT_BUTTONS', j, 2); } else if (CR == -429) { WelinkSendHald(8, 'OP_XINPUT_BUTTONS', j, 8); } else if (CR == -1000) { WelinkSendHald(1, 'OP_XINPUT_BUTTONS', j, 1); } } else { WelinkSendHald(0, 'OP_XINPUT_BUTTONS', j); } } } } else { // 无记录的 if (LX != 0) { WelinkSendHald(LX, 'OP_XINPUT_THUMB_LX', j); } if (LY != 0) { WelinkSendHald(LY, 'OP_XINPUT_THUMB_LY', j); } if (RX != 0) { WelinkSendHald(RX, 'OP_XINPUT_THUMB_RX', j); } if (RY != 0) { WelinkSendHald(RY, 'OP_XINPUT_THUMB_RY', j); } // 判断是否安卓模式并且按下 if ((handModel.indexOf('360') == -1 && handModel.indexOf('xbox') == -1) || handModel.indexOf('wireless controller') != -1) { if (CR <= 1000) { if (CR == 714) { WelinkSendHald(4, 'OP_XINPUT_BUTTONS', j, 4); } else if (CR == 143) { WelinkSendHald(2, 'OP_XINPUT_BUTTONS', j, 2); } else if (CR == -429) { WelinkSendHald(8, 'OP_XINPUT_BUTTONS', j, 8); } else if (CR == -1000) { WelinkSendHald(1, 'OP_XINPUT_BUTTONS', j, 1); } } else { WelinkSendHald(0, 'OP_XINPUT_BUTTONS', j); } } } thisStatus.axes = [LX, LY, RX, RY, CR]; // 记录状态 handleStatus[j] = thisStatus; } }; }; // 处理虚拟手柄按键<键盘按键/touch事件> let WelinkOnGamePadButton = (userIndex, keycode, action) => { if (action == KEY_DOWN) { WelinkSendHald(keycode * 1, 'OP_XINPUT_BUTTONS', userIndex, keycode * 1); } else { WelinkSendHald(0, 'OP_XINPUT_BUTTONS', userIndex, keycode * 1); } }; // 处理虚拟手柄摇杆<键盘按键/touch事件> let WelinkOnGamePadAxis = (userIndex, type, xValue, yValue) => { // 处理左摇杆 if (type == AXIS_LXLY) { WelinkSendHald(xValue, 'OP_XINPUT_THUMB_LX', userIndex); WelinkSendHald(yValue, 'OP_XINPUT_THUMB_LY', userIndex); } // 处理右摇杆 if (type == AXIS_RXRY) { WelinkSendHald(xValue, 'OP_XINPUT_THUMB_RX', userIndex); WelinkSendHald(yValue, 'OP_XINPUT_THUMB_RY', userIndex); } // 处理LT if (type == AXIS_LT) { WelinkSendHald(xValue, 'OP_XINPUT_LEFT_TRIGGER', userIndex); } // 处理RT if (type == AXIS_RT) { WelinkSendHald(yValue, 'OP_XINPUT_RIGHT_TRIGGER', userIndex); } }; const clearAllEvents = () => { window.removeEventListener('gamepadconnected', gamepadconnected); window.removeEventListener('gamepaddisconnected', gamepaddisconnected); gamepadconnected = null; gamepaddisconnected = null; } ///统一响应按键 let WelinkSendHald = (msg, type = 'OP_XINPUT_BUTTONS', index, action) => { // let index = index ? parseInt(index) : 0; if (type == 'OP_XINPUT_BUTTONS') { if (msg !== 0) { endMsg += action; } else { endMsg -= action; } //处理按键 } else { //处理摇杆和轴等信息 } };