Skip to content

Instantly share code, notes, and snippets.

@sketchpunk
Last active March 28, 2019 21:00
Show Gist options
  • Save sketchpunk/ec6031d0da8179be631bb9bca0a99e03 to your computer and use it in GitHub Desktop.
Save sketchpunk/ec6031d0da8179be631bb9bca0a99e03 to your computer and use it in GitHub Desktop.
let GamepadList = new Array();
class GamepadTracker{
constructor( profile ){
this.gpIndex = -1;
this.profile = profile;
this.timestamp = 0;
this.hasChanged = false;
this.onConnectBind = this.onConnect.bind( this );
this.onDisconnectBind = this.onDisconnect.bind( this );
window.addEventListener("gamepadconnected", this.onConnectBind );
window.addEventListener("gamepaddisconnected", this.onDisconnectBind );
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for( let i in GamepadList ){
if( GamepadList[i].indexOf( this.profile.id ) != -1 && this.gpIndex == -1){
this.gpIndex = i;
console.log("Controller found and ready : ", this.profile.id );
}
}
}
onDisconnect(e){ console.log("Gamepad - disconnect",e); }
onConnect(e){
GamepadList[ e.gamepad.index ] = e.gamepad.id;
console.log("Gamepad - Index : %d, ID: %s", e.gamepad.index, e.gamepad.id);
if( e.gamepad.id.indexOf( this.profile.id ) != -1 && this.gpIndex == -1){
this.gpIndex = e.gamepad.index;
console.log("Controller found and ready : ", this.profile.id );
}
}
update(){
if(this.gpIndex == -1) return;
let gp = navigator.getGamepads()[ this.gpIndex ];
if( gp.timestamp == this.timestamp ){ this.hasChanged = false; return; }
this.timestamp = gp.timestamp;
this.hasChanged = true;
this.profile.update( gp );
}
}
//###########################################################################
class Xbox{
constructor(){
this.deadZone = 0.1;
this.id = "XInput";
this.joyL = { x:0, y:0, xIdx:0, yIdx:1, isActive:false };
this.joyR = { x:0, y:0, xIdx:2, yIdx:3, isActive:false };
this.joys = [ "joyL", "joyR" ];
this.a = { idx:0, state:0, hasChanged:false };
this.b = { idx:1, state:0, hasChanged:false };
this.x = { idx:2, state:0, hasChanged:false };
this.y = { idx:3, state:0, hasChanged:false };
this.bumperL = { idx:4, state:0, hasChanged:false };
this.bumperR = { idx:5, state:0, hasChanged:false };
this.triggerL = { idx:6, state:0, hasChanged:false };
this.triggerR = { idx:7, state:0, hasChanged:false };
this.back = { idx:8, state:0, hasChanged:false };
this.start = { idx:9, state:0, hasChanged:false };
this.stickL = { idx:10, state:0, hasChanged:false };
this.stickR = { idx:11, state:0, hasChanged:false };
this.dup = { idx:12, state:0, hasChanged:false };
this.ddown = { idx:13, state:0, hasChanged:false };
this.dleft = { idx:14, state:0, hasChanged:false };
this.dright = { idx:15, state:0, hasChanged:false };
this.btns = [
"a", "b", "x", "y", "bumperL", "bumperR", "triggerL", "triggerR",
"back", "start", "stickL", "stickR", "dup", "ddown", "dleft", "dright"
];
}
update( gp ){
let itm, i, v;
//Update Button Data
for( i of this.btns ){
itm = this[ i ];
v = ( gp.buttons[ itm.idx ].value > this.deadZone )? gp.buttons[ itm.idx ].value : 0;
itm.hasChanged = (v != itm.state);
itm.state = v;
}
//Update Joystick Data
for( i of this.joys ){
itm = this[ i ];
//Flip Y, Up is -1, rather it be positive and down be negative.
//Flip X, Fungi uses Left, not Right, so flipping sign will make math work correctly
itm.x = ( Math.abs( gp.axes[ itm.xIdx ] ) > this.deadZone)? -gp.axes[ itm.xIdx ] : 0;
itm.y = ( Math.abs( gp.axes[ itm.yIdx ] ) > this.deadZone)? -gp.axes[ itm.yIdx ] : 0;
itm.isActive = ( itm.x != 0 || itm.y != 0 );
}
}
}
//###########################################################################
class Hotas{
constructor(){
this.deadZone = 0.05;
this.id = "Hotas";
this.pitch = { v:0, idx:1, isActive:false };
this.roll = { v:0, idx:0, isActive:false };
this.yaw = { v:0, idx:5, isActive:false };
this.thrust = { v:0, idx:2, isActive:false };
this.rocker = { v:0, idx:6, isActive:false };
this.hat = { x:0, y:0, idx:9, isActive:false };
this.axis = [ "pitch", "roll", "yaw", "thrust", "rocker" ];
this.L1 = { idx:1, state:0, hasChanged:false };
this.L2 = { idx:9, state:0, hasChanged:false };
this.L3 = { idx:3, state:0, hasChanged:false };
this.R1 = { idx:0, state:0, hasChanged:false };
this.R2 = { idx:8, state:0, hasChanged:false };
this.R3 = { idx:2, state:0, hasChanged:false };
this.B5 = { idx:4, state:0, hasChanged:false };
this.B6 = { idx:5, state:0, hasChanged:false };
this.B7 = { idx:6, state:0, hasChanged:false };
this.B8 = { idx:7, state:0, hasChanged:false };
this.btns = [ "L1", "L2", "L3", "R1", "R2", "R3", "B5", "B6", "B7", "B8" ];
}
update( gp ){
let i, itm, v;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for( i of this.axis ){
itm = this[ i ];
v = ( Math.abs( gp.axes[ itm.idx ] ) > this.deadZone )? gp.axes[ itm.idx ] : 0;
itm.v = v;
itm.isActive = ( v != 0 );
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
this.hat.v = gp.axes[ this.hat.idx ];
switch( this.hat.v ){
case -1: this.hat.y = 1; this.hat.x = 0; break; // Up
case 0.14285719394683838: this.hat.y = -1; this.hat.x = 0; break; // Down
case 0.7142857313156128: this.hat.x = -1; this.hat.y = 0; break; // Left
case -0.4285714030265808: this.hat.x = 1; this.hat.y = 0; break; // Right
default: this.hat.x = 0; this.hat.y = 0; break; // Unchanged
}
this.hat.isActive = ( this.hat.v != 0 );
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for( i of this.btns ){
itm = this[ i ];
v = ( gp.buttons[ itm.idx ].value > this.deadZone )? gp.buttons[ itm.idx ].value : 0;
itm.hasChanged = (v != itm.state);
itm.state = v;
}
}
}
//###########################################################################
let Gamepad = { Xbox : Xbox, Hotas : Hotas };
export default GamepadTracker;
export { Gamepad };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment