├── docs └── empty ├── tests └── empty ├── vendor └── empty ├── .gitignore ├── examples ├── mouse │ ├── pointer.png │ └── index.html ├── game │ ├── js │ │ ├── background.js │ │ ├── player.js │ │ ├── levelsettings.js │ │ └── game.js │ └── index.html └── simple │ └── index.html ├── LICENSE-MIT ├── README.md └── lib └── gamepad.js /docs/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | DS_Store 3 | -------------------------------------------------------------------------------- /examples/mouse/pointer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alaingilbert/GamepadJs/HEAD/examples/mouse/pointer.png -------------------------------------------------------------------------------- /examples/game/js/background.js: -------------------------------------------------------------------------------- 1 | var Background = function() { 2 | }; 3 | 4 | 5 | Background.prototype.update = function(deltaTime) { 6 | }; 7 | 8 | 9 | Background.prototype.render = function() { 10 | }; 11 | -------------------------------------------------------------------------------- /examples/game/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/game/js/player.js: -------------------------------------------------------------------------------- 1 | var Player = function() { 2 | this.x = 100; 3 | this.y = 100; 4 | this.w = 100; 5 | this.h = 100; 6 | this.velocity = 200; 7 | }; 8 | 9 | 10 | Player.prototype.update = function(deltaTime) { 11 | if (Game.pad[Game.Controls.LEFT]) { 12 | this.x -= deltaTime / 1000 * this.velocity; 13 | } 14 | if (Game.pad[Game.Controls.RIGHT]) { 15 | this.x += deltaTime / 1000 * this.velocity; 16 | } 17 | if (Game.pad[Game.Controls.UP]) { 18 | this.y -= deltaTime / 1000 * this.velocity; 19 | } 20 | if (Game.pad[Game.Controls.DOWN]) { 21 | this.y += deltaTime / 1000 * this.velocity; 22 | } 23 | }; 24 | 25 | 26 | Player.prototype.render = function() { 27 | var c = Game.ctx; 28 | c.save(); 29 | c.translate(this.x, this.y); 30 | 31 | c.fillRect(0, 0, this.w, this.h); 32 | 33 | c.restore(); 34 | }; 35 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2012,2013 Alain Gilbert 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to 5 | deal in the Software without restriction, including without limitation the 6 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 | sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 | IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/game/js/levelsettings.js: -------------------------------------------------------------------------------- 1 | var LevelSettings = function() { 2 | var self = this; 3 | this.step = 0; 4 | this.stepSucceed = false; 5 | this.changeStep(); 6 | }; 7 | 8 | 9 | LevelSettings.prototype.changeStep = function() { 10 | var self = this; 11 | Game.pad.once('buttondown', function(evt) { 12 | switch (self.step) { 13 | case 0: 14 | Game.Controls.LEFT = evt.button; 15 | self.step++; 16 | self.changeStep(); 17 | break; 18 | case 1: 19 | Game.Controls.RIGHT = evt.button; 20 | self.step++; 21 | self.changeStep(); 22 | break; 23 | case 2: 24 | Game.Controls.UP = evt.button; 25 | self.step++; 26 | self.changeStep(); 27 | break; 28 | case 3: 29 | Game.Controls.DOWN = evt.button; 30 | self.step++; 31 | self.changeStep(); 32 | break; 33 | } 34 | }); 35 | }; 36 | 37 | 38 | LevelSettings.prototype.update = function(deltaTime) { 39 | }; 40 | 41 | 42 | LevelSettings.prototype.render = function() { 43 | var c = Game.ctx; 44 | c.save(); 45 | 46 | c.font = '20px sans-serif'; 47 | c.textAlign = 'center'; 48 | switch (this.step) { 49 | case 0: 50 | c.fillText('Set your LEFT button.', Game.canvas.width/2, Game.canvas.height/2 - 20); 51 | c.fillText('(Waiting for player interaction)', Game.canvas.width/2, Game.canvas.height/2 + 20); 52 | break; 53 | case 1: 54 | c.fillText('Set your RIGHT button.', Game.canvas.width/2, Game.canvas.height/2 - 20); 55 | c.fillText('(Waiting for player interaction)', Game.canvas.width/2, Game.canvas.height/2 + 20); 56 | break; 57 | case 2: 58 | c.fillText('Set your UP button.', Game.canvas.width/2, Game.canvas.height/2 - 20); 59 | c.fillText('(Waiting for player interaction)', Game.canvas.width/2, Game.canvas.height/2 + 20); 60 | break; 61 | case 3: 62 | c.fillText('Set your DOWN button.', Game.canvas.width/2, Game.canvas.height/2 - 20); 63 | c.fillText('(Waiting for player interaction)', Game.canvas.width/2, Game.canvas.height/2 + 20); 64 | break; 65 | case 4: 66 | c.fillText('CONGRATS', 100, 100); 67 | Game.state = Game.States.GAME; 68 | break; 69 | } 70 | 71 | c.restore(); 72 | }; 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gamepad API 2 | 3 | Allows you to use gamepads in javascript. 4 | 5 | ![Screen shot 1](http://us.cdn4.123rf.com/168nwm/chisnikov/chisnikov1104/chisnikov110400057/9267738-boitier-de-commande-contour-noir-sur-blanc-bakcground-illustration-vectorielle.jpg) 6 | 7 | ## Quick start 8 | 9 | ```html 10 | 11 | ``` 12 | 13 | ```js 14 | var pad = Gamepads.get(0); 15 | ``` 16 | 17 | In the game loop, you have to put the following command. 18 | 19 | It will update the state of all the connected gamepads. 20 | 21 | ```js 22 | Gamepads.update(); 23 | ``` 24 | 25 | ## Properties 26 | 27 | All the buttons/joysticks states are accessible like this: 28 | 29 | Get a button state (replace X by a number). Return a value in the range [0..1] 30 | 31 | ```js 32 | pad.BUTTON_X; 33 | ``` 34 | 35 | Get a joystick state (replace X by a number). Return a value in the range [-1..1] 36 | 37 | ```js 38 | pad.AXE_X; 39 | ``` 40 | 41 | 42 | If the gamepad is known, you can access it with some user friendly names: 43 | 44 | ```js 45 | pad.A; 46 | pad.B; 47 | pad.X; 48 | pad.Y; 49 | pad.LEFT_SHOULDER_0; 50 | pad.RIGHT_SHOULDER_0; 51 | pad.LEFT_SHOULDER_1; 52 | pad.RIGHT_SHOULDER_1; 53 | pad.SELECT; 54 | pad.START; 55 | pad.LEFT_STICK_BUTTON; 56 | pad.LEFT_STICK_BUTTON; 57 | pad.UP; 58 | pad.DOWN; 59 | pad.LEFT; 60 | pad.RIGHT; 61 | pad.LEFT_STICK_X; 62 | pad.LEFT_STICK_Y; 63 | pad.RIGHT_STICK_X; 64 | pad.RIGHT_STICK_Y; 65 | ``` 66 | 67 | 68 | ## Events 69 | 70 | ### connected 71 | 72 | ```js 73 | pad.on('connected', function(evt) { console.log(evt); }); 74 | // {"index":0,"timestamp":1338874409909,"type":"connected"} 75 | ``` 76 | 77 | ### disconnected 78 | 79 | ```js 80 | pad.on('disconnected', function(evt) { console.log(evt); }); 81 | // {"timestamp":1338874409909,"type":"disconnected"} 82 | ``` 83 | 84 | ### axismove 85 | 86 | ```js 87 | pad.on('axismove', function(evt) { console.log(evt); }); 88 | // {"button":"RIGHT_STICK_X","timestamp":1338874409909, 89 | // "type":"axismove","value":0.003921627998352051} 90 | ``` 91 | 92 | ### buttondown 93 | 94 | ```js 95 | pad.on('buttondown', function(evt) { console.log(evt); }); 96 | // {"button":"A","timestamp":1338873574415,"type":"buttondown"} 97 | ``` 98 | 99 | ### buttonup 100 | 101 | ```js 102 | pad.on('buttonup', function(evt) { console.log(evt); }); 103 | // {"button":"A","timestamp":1338873574415,"type":"buttonup"} 104 | ``` 105 | 106 | ## Author 107 | 108 | Alain Gilbert ([@alain_gilbert](https://twitter.com/alain_gilbert)) 109 | -------------------------------------------------------------------------------- /examples/game/js/game.js: -------------------------------------------------------------------------------- 1 | var Game = {}; 2 | 3 | 4 | Game.init = function() { 5 | Game.canvas = document.getElementById('canvas'); 6 | Game.ctx = Game.canvas.getContext('2d'); 7 | Game.background = new Background(); 8 | Game.player = new Player(); 9 | Game.pad = Gamepads.get(0); 10 | Game.States = {BIND_KEYS: 0, GAME: 1, UNSUPPORTED: 2}; 11 | Game.lastFrame = new Date().getTime(); 12 | 13 | Game.Controls = {LEFT: null, RIGHT: null, UP: null, DOWN: null}; 14 | 15 | if (Gamepads.supported) { 16 | Game.levelSettings = new LevelSettings(); 17 | Game.state = Game.States.BIND_KEYS; 18 | } else { 19 | Game.state = Game.States.UNSUPPORTED; 20 | } 21 | 22 | Game.cycle(); 23 | }; 24 | 25 | 26 | Game.update = function(deltaTime) { 27 | switch (Game.state) { 28 | case Game.States.BIND_KEYS: 29 | Gamepads.update(); 30 | Game.levelSettings.update(deltaTime); 31 | break; 32 | case Game.States.GAME: 33 | Gamepads.update(); 34 | Game.background.update(deltaTime); 35 | Game.player.update(deltaTime); 36 | break; 37 | case Game.States.UNSUPPORTED: 38 | break; 39 | } 40 | }; 41 | 42 | 43 | Game.render = function() { 44 | var c = Game.ctx; 45 | c.save(); 46 | c.clearRect(0, 0, Game.canvas.width, Game.canvas.height); 47 | 48 | switch (Game.state) { 49 | case Game.States.BIND_KEYS: 50 | Game.levelSettings.render(); 51 | break; 52 | case Game.States.GAME: 53 | Game.background.render(); 54 | Game.player.render(); 55 | break; 56 | case Game.States.UNSUPPORTED: 57 | c.textAlign = 'center'; 58 | c.font = '20px sans-serif'; 59 | c.fillText('Your browser does not support html5 gamepads api.', 60 | Game.canvas.width/2, Game.canvas.height/2); 61 | break; 62 | } 63 | 64 | c.strokeRect(0, 0, Game.canvas.width, Game.canvas.height); 65 | c.restore(); 66 | }; 67 | 68 | 69 | Game.cycle = function() { 70 | var deltaTime = new Date().getTime() - Game.lastFrame; 71 | Game.update(deltaTime); 72 | Game.render(); 73 | Game.lastFrame = new Date().getTime(); 74 | requestAnimFrame(Game.cycle); 75 | }; 76 | 77 | 78 | window.requestAnimFrame = (function(){ 79 | return window.requestAnimationFrame || // La forme standardisée 80 | window.webkitRequestAnimationFrame || // Pour Chrome et Safari 81 | window.mozRequestAnimationFrame || // Pour Firefox 82 | window.oRequestAnimationFrame || // Pour Opera 83 | window.msRequestAnimationFrame || // Pour Internet Explorer 84 | function(callback){ // Pour les élèves du dernier rang 85 | window.setTimeout(callback, 1000 / 60); 86 | }; 87 | })(); 88 | 89 | 90 | document.addEventListener('DOMContentLoaded', function() { Game.init(); }); 91 | -------------------------------------------------------------------------------- /examples/simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Gamepad 5 | 6 | 7 | 8 | 9 |
10 | 11 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /examples/mouse/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mouse example 5 | 6 | 19 | 20 | 21 | 22 | 23 |
24 | 25 |
26 |
27 |
28 |
29 |
30 |
31 | Link 1
32 | This is a longer link
33 | Link 3
34 | 35 | 36 | 295 | 296 | 297 | 298 | 299 | -------------------------------------------------------------------------------- /lib/gamepad.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012,2013 Alain Gilbert 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | 25 | /** 26 | * Events manager. 27 | * @constructor 28 | */ 29 | var EventEmitter = function() { 30 | this.callbacks_ = {}; 31 | }; 32 | 33 | 34 | /** 35 | * Listen for a specific signal. 36 | * @param {string} signal Signal to listen on. 37 | * @param {Function} callback Callback. 38 | * @return {boolean} False if the callback already exists, true otherwise. 39 | */ 40 | EventEmitter.prototype.on = function(signal, callback) { 41 | var callbacks = this.callbacks_[signal] || []; 42 | for (var i = 0; i < callbacks.length; i++) { 43 | if (callback == callbacks[i]) { 44 | return false; 45 | } 46 | } 47 | if (!this.callbacks_[signal]) { this.callbacks_[signal] = []; } 48 | this.callbacks_[signal].push(callback); 49 | return true; 50 | }; 51 | 52 | 53 | /** 54 | * Listen once for a specific signal. 55 | * @param {string} signal Signal to listen on. 56 | * @param {Function} callback Callback. 57 | * @return {Object} The object itself. 58 | */ 59 | EventEmitter.prototype.once = function(signal, callback) { 60 | var self = this; 61 | var g = function() { 62 | self.removeListener(signal, g); 63 | callback.apply(this, arguments); 64 | }; 65 | 66 | g.callback = callback; 67 | self.on(signal, g); 68 | 69 | return this; 70 | }; 71 | 72 | 73 | /** 74 | * Remove a callback. 75 | * @param {string} signal Signal to listen on. 76 | * @param {Function} callback Callback. 77 | * @return {Object} The object itself. 78 | */ 79 | EventEmitter.prototype.removeListener = function(signal, callback) { 80 | if (!this.callbacks_ || !this.callbacks_[signal]) { return this; } 81 | 82 | var callbacks = this.callbacks_[signal]; 83 | for (var i = 0; i < callbacks.length; i++) { 84 | if (callbacks[i] === callback || 85 | (callbacks[i].callback && callbacks[i].callback === callback)) 86 | { 87 | callbacks.splice(i, 1); 88 | break; 89 | } 90 | } 91 | 92 | return this; 93 | }; 94 | 95 | 96 | /** 97 | * Emit a signal. 98 | * @param {string} signal Signal to emit. 99 | * @param {Object} evt Event to be emitted. 100 | * @return {boolean} False if there is no callbacks, true otherwise. 101 | */ 102 | EventEmitter.prototype.emit = function(signal, evt) { 103 | var callbacks = this.callbacks_[signal]; 104 | if (!callbacks) { return false; } 105 | for (var i = 0; i < callbacks.length; i++) { 106 | callbacks[i].call(this, evt); 107 | } 108 | return true; 109 | }; 110 | 111 | 112 | /** 113 | * Gamepads global variable. 114 | */ 115 | var Gamepads = {}; 116 | 117 | 118 | /** 119 | * 120 | */ 121 | Gamepads.isFirefox_ = navigator.userAgent.indexOf('Firefox/') != -1; 122 | 123 | /** */ 124 | (function() { 125 | if (Gamepads.isFirefox_) { 126 | navigator.mozGamepads = [null, null, null, null]; 127 | var mozConnectHandler = function(evt) { 128 | console.log('CONNECTED'); 129 | navigator.mozGamepads[evt.gamepad.index] = evt.gamepad; 130 | } 131 | var mozDisconnectHandler = function(evt) { 132 | navigator.mozGamepads[evt.gamepad.index] = undefined; 133 | } 134 | window.addEventListener("MozGamepadConnected", mozConnectHandler, false); 135 | window.addEventListener("MozGamepadDisconnected", mozDisconnectHandler, false); 136 | } 137 | })(); 138 | 139 | 140 | /** 141 | * Array that contain all the Gamepad objects. 142 | * @type {Array.} 143 | */ 144 | Gamepads.pads = []; 145 | 146 | 147 | /** 148 | * Is the Gamepads initialized. 149 | * @private 150 | */ 151 | Gamepads.isInit_ = false; 152 | 153 | 154 | /** 155 | * Get all the gamepads connected. 156 | * @return {Object} All gamepads. 157 | */ 158 | Gamepads.getGamepads = function() { 159 | return navigator.webkitGamepads || 160 | navigator.mozGamepads || 161 | navigator.gamepads; 162 | }; 163 | 164 | 165 | /** 166 | * Verify that the browser support the gamepad api. 167 | */ 168 | Gamepads.supported = Gamepads.getGamepads() != undefined; 169 | 170 | 171 | /** 172 | * Get the gamepad at the specified index. 173 | * @param {number} idx The index in the gamepads array. 174 | * @return {Gamepad} Get the Gamepad at the specified index. 175 | */ 176 | Gamepads.get = function(idx) { 177 | if (!Gamepads.isInit_) { Gamepads.update(); } 178 | return Gamepads.pads[idx]; 179 | }; 180 | 181 | 182 | /** 183 | * Get the current gamepad count. 184 | * @return {number} The number of Gamepads detedted. 185 | */ 186 | Gamepads.length = function() { 187 | var count = 0; 188 | for (var i = 0; i < Gamepads.pads.length; i++) { 189 | if (Gamepads.pads[i]) { 190 | count++; 191 | } 192 | } 193 | return count; 194 | }; 195 | 196 | 197 | /** 198 | * Update all gamepads state. 199 | */ 200 | Gamepads.update = function() { 201 | Gamepads.isInit_ = true; 202 | var pads = Gamepads.getGamepads(); 203 | if (!pads) { return false; } 204 | for (var i = 0; i < pads.length; i++) { 205 | if (!Gamepads.pads[i]) { 206 | Gamepads.pads[i] = new Gamepad(pads[i]); 207 | } 208 | Gamepads.pads[i].refresh(pads[i]); 209 | } 210 | }; 211 | 212 | 213 | 214 | /** 215 | * Represent a Gamepad. 216 | * @param {Object} params Parameters. 217 | * @constructor 218 | * @extends {EventEmitter} 219 | */ 220 | var Gamepad = function(params) { 221 | params = params || {}; 222 | EventEmitter.call(this); 223 | this.id = params.id; 224 | this.previousState = {}; 225 | this.isConnected = false; 226 | this.isKnown_ = false; 227 | this.lastUpdate_ = {}; 228 | this.deadZone_ = 0.07; 229 | }; 230 | 231 | 232 | /** */ 233 | Gamepad.prototype.__proto__ = EventEmitter.prototype; 234 | 235 | 236 | /** 237 | * Refresh the Gamepad properties. 238 | * @param {Object} params Parameters. 239 | */ 240 | Gamepad.prototype.refresh = function(params) { 241 | params = params || {}; 242 | if (params.id) { 243 | if (!this.isConnected) { 244 | this.id = params.id; 245 | var evt = { type: 'connected', 246 | timestamp: new Date().getTime(), 247 | index: params.index 248 | }; 249 | this.emit('connected', evt); 250 | } 251 | this.isConnected = true; 252 | this.map(params); 253 | } else { 254 | if (this.lastUpdate_.id) { 255 | var evt = { type: 'disconnected', 256 | timestamp: new Date().getTime() 257 | }; 258 | this.emit('disconnected', evt); 259 | this.isConnected = false; 260 | } 261 | } 262 | this.lastUpdate_ = params; 263 | }; 264 | 265 | 266 | /** 267 | * Set all the Gamepad properties. 268 | * @param {Object} map Mapping. 269 | */ 270 | Gamepad.prototype.setMap = function(map) { 271 | for (var key in map) { 272 | 273 | // If the key was defined, and is now different. 274 | if (this.previousState[key] !== undefined && 275 | map[key] != this.previousState[key]) 276 | { 277 | if (key.indexOf('STICK_') != -1 || 278 | key.indexOf('AXE_') != -1) 279 | { 280 | var evt = { 281 | button: key, 282 | timestamp: new Date().getTime(), 283 | type: 'axismove', 284 | value: map[key], 285 | }; 286 | this.emit('axismove', evt); 287 | 288 | 289 | // Buttons 290 | } else { 291 | 292 | // If the gamepad is known, we don't trigger the events for the 293 | // default mapping buttons. 294 | if (this.isKnown_ && 295 | (key.indexOf('BUTTON_') != -1 || 296 | key.indexOf('AXE_') != -1)) 297 | { 298 | continue; 299 | } 300 | 301 | var evt = { 302 | button: key, 303 | timestamp: new Date().getTime() 304 | }; 305 | if (map[key] === 1) { 306 | evt.type = 'buttondown'; 307 | this.emit('buttondown', evt); 308 | } else if (map[key] === 0) { 309 | evt.type = 'buttonup'; 310 | this.emit('buttonup', evt); 311 | } 312 | } 313 | } 314 | this[key] = map[key]; 315 | } 316 | }; 317 | 318 | 319 | /** 320 | * Get the correct mapping. 321 | * @param {Object} params Paramters. 322 | */ 323 | Gamepad.prototype.map = function(params) { 324 | var map = {}; 325 | switch (this.getType()) { 326 | case 'Logitech F310': 327 | this.isKnown_ = true; 328 | map = this.getLogitechF310Map(params); 329 | break; 330 | } 331 | var defaultMap = this.getDefaultMapping(params); 332 | for (var key in defaultMap) { 333 | map[key] = defaultMap[key]; 334 | } 335 | this.setMap(map); 336 | this.previousState = map; 337 | }; 338 | 339 | 340 | /** 341 | * Get the Logitech F310 buttons mapping. 342 | * @param {Object} params Parameters. 343 | * @return {Object} The Logitech F310 mapping. 344 | */ 345 | Gamepad.prototype.getLogitechF310Map = function(params) { 346 | return { 347 | A: params.buttons[0] || 0, 348 | B: params.buttons[1] || 0, 349 | X: params.buttons[2] || 0, 350 | Y: params.buttons[3] || 0, 351 | LEFT_SHOULDER_0: params.buttons[4] || 0, 352 | RIGHT_SHOULDER_0: params.buttons[5] || 0, 353 | LEFT_SHOULDER_1: params.buttons[6] || 0, 354 | RIGHT_SHOULDER_1: params.buttons[7] || 0, 355 | SELECT: params.buttons[8] || 0, 356 | START: params.buttons[9] || 0, 357 | LEFT_STICK_BUTTON: params.buttons[10] || 0, 358 | RIGHT_STICK_BUTTON: params.buttons[11] || 0, 359 | UP: params.buttons[12] || 0, 360 | DOWN: params.buttons[13] || 0, 361 | LEFT: params.buttons[14] || 0, 362 | RIGHT: params.buttons[15] || 0, 363 | LEFT_STICK_X: this.adjustWithDeadZone(params.axes[0]) || 0, 364 | LEFT_STICK_Y: this.adjustWithDeadZone(params.axes[1]) || 0, 365 | RIGHT_STICK_X: this.adjustWithDeadZone(params.axes[2]) || 0, 366 | RIGHT_STICK_Y: this.adjustWithDeadZone(params.axes[3]) || 0 367 | }; 368 | }; 369 | 370 | 371 | /** 372 | * Get the default mapping. 373 | * @param {Object} params Parameters. 374 | * @return {Object} The default mapping. 375 | */ 376 | Gamepad.prototype.getDefaultMapping = function(params) { 377 | var mapping = {}; 378 | for (var i = 0; i < params.buttons.length; i++) { 379 | mapping['BUTTON_' + i] = params.buttons[i]; 380 | } 381 | for (var i = 0; i < params.axes.length; i++) { 382 | var value = params.axes[i]; 383 | mapping['AXE_' + i] = this.adjustWithDeadZone(params.axes[i]); 384 | } 385 | return mapping; 386 | }; 387 | 388 | 389 | /** 390 | * @param {number} value The real joystick value. 391 | * @return {number} The new value. 392 | */ 393 | Gamepad.prototype.adjustWithDeadZone = function(value) { 394 | if (value + this.deadZone_ >= 1) { value = 1; } 395 | if (value - this.deadZone_ <= -1) { value = -1; } 396 | if (value <= this.deadZone_ && value >= -this.deadZone_) { value = 0; } 397 | return value; 398 | }; 399 | 400 | 401 | /** 402 | * Get the gamepad type. 403 | * @return {string} The Gamepad type. 404 | */ 405 | Gamepad.prototype.getType = function() { 406 | if (this.id.indexOf('Vendor: 046d') != -1 && 407 | this.id.indexOf('Product: c216') != -1) 408 | { 409 | return 'Logitech F310'; 410 | } 411 | }; 412 | --------------------------------------------------------------------------------