Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

1 decade ago by spacelime

I pieced together snippets of code here and there to get gamepad support working for Impact. The code I found at first was not compatible with Chrome 22 or higher and it only supported Xbox and PS2 controllers. I made it recognize any generic gamepad, but you might want to adjust the button mapping a bit to suit you. Also I've not modified it to work for Firefox yet. If you can get it working, please let me know =)

How to do this:

1) add the line
'plugins.gamepad.gamepad'

under .requires in main.js

2) under your main entity's update function, add this:
// Load gamepad state, if not active then set to 0
var pads = Gamepad.getStates();
    if (pads[0] == undefined) pads[0] = 0;

3) test for input state with for example:

if( pads[0].leftStickX == -1 )
{
   // move left
}

4) add this at the end of the update function:
// To make sure that gamepad.js can set it's variables properly
pads[0] = undefined;

5) make a file called gamepad.js in lib/plugins/gamepad/ and paste this into it:
/*
	gamepad.js, See README for copyright and usage instructions.
*/
ig.module( 
	'plugins.gamepad.gamepad' 
)
.requires(

)
.defines(function() {
   var getField = function() {
  return navigator.webkitGamepads || navigator.mozGamepads || navigator.gamepads ||
  navigator.webkitGetGamepads() || navigator.mozGetGamepads() || navigator.getGamepads();
};

    var Item = function() {
        this.leftStickX = 0.0;
        this.leftStickY = 0.0;
        this.rightStickX = 0.0;
        this.rightStickY = 0.0;
        this.faceButton0 = 0.0;
        this.faceButton1 = 0.0;
        this.faceButton2 = 0.0;
        this.faceButton3 = 0.0;
        this.leftShoulder0 = 0.0;
        this.rightShoulder0 = 0.0;
        this.leftShoulder1 = 0.0;
        this.rightShoulder1 = 0.0;
        this.select = 0.0;
        this.start = 0.0;
        this.leftStickButton = 0.0;
        this.rightStickButton = 0.0;
        this.dpadUp = 0.0;
        this.dpadDown = 0.0;
        this.dpadLeft = 0.0;
        this.dpadRight = 0.0;
        this.deadZoneLeftStick = 0.25;
        this.deadZoneRightStick = 0.25;
        this.deadZoneShoulder0 = 0.0;
        this.deadZoneShoulder1 = 0.0;
        this.images = Gamepad.ImageDataUrls_Unknown;
        this.name = "Unknown";
    };

    var deepCopy = function(into, from) {
        into.leftStickX = from.leftStickX;
        into.leftStickY = from.leftStickY;
        into.rightStickX = from.rightStickX;
        into.rightStickY = from.rightStickY;
        into.faceButton0 = from.faceButton0;
        into.faceButton1 = from.faceButton1;
        into.faceButton2 = from.faceButton2;
        into.faceButton3 = from.faceButton3;
        into.leftShoulder0 = from.leftShoulder0;
        into.rightShoulder0 = from.rightShoulder0;
        into.leftShoulder1 = from.leftShoulder1;
        into.rightShoulder1 = from.rightShoulder1;
        into.select = from.select;
        into.start = from.start;
        into.leftStickButton = from.leftStickButton;
        into.rightStickButton = from.rightStickButton;
        into.dpadUp = from.dpadUp;
        into.dpadDown = from.dpadDown;
        into.dpadLeft = from.dpadLeft;
        into.dpadRight = from.dpadRight;
    };

    var contains = function(lookIn, forWhat) { return lookIn.indexOf(forWhat) != -1; };
    var userAgent = navigator.userAgent;
    var isWindows = contains(userAgent, 'Windows NT');
    var isMac = contains(userAgent, 'Macintosh');
    var isChrome = contains(userAgent, 'Chrome/');
    var isFirefox = contains(userAgent, 'Firefox/');

    var axisToButton = function(value) {
        return (value + 1.0) / 2.0;
    }

    if (isFirefox) {
        // todo; current moz nightly does not define this, so we'll always
        // return true for .supported on that Firefox.
        navigator.mozGamepads = [];
        var mozConnectHandler = function(e) {
            navigator.mozGamepads[e.gamepad.index] = e.gamepad;
        }
        var mozDisconnectHandler = function(e) {
            navigator.mozGamepads[e.gamepad.index] = undefined;
        }
        window.addEventListener("MozGamepadConnected", mozConnectHandler);
        window.addEventListener("MozGamepadDisconnected", mozDisconnectHandler);
    }

    var mapPad = function(raw, mapped) {
        var len = active.length;
        for (var i = 0; i < len; ++i) {
            var entry = active[i];
            var ss1 = entry[0];
            var ss2 = entry[1];
            if (contains(raw.id, ss1) && contains(raw.id, ss2)) {
                var handler = entry[2];
                handler(raw, mapped);
                var deviceident = entry[3];
                mapped.name = deviceident + " Player " + (raw.index + 1);
                // todo; apply dead zones to mapped here
                return;
            }
        }
        var entry = active[0];
        var handler = entry[2];
        handler(raw, mapped);
        var deviceident = entry[3];
        mapped.name = deviceident + " Player " + (raw.index + 1);
    };

    var mapIndividualPad = function(rawPads, i) {
        var raw = rawPads[i];
        if (!raw) {
            prevData[i] = undefined;
            curData[i] = undefined;
            return;
        }
        if (curData[i] === undefined) {
            prevData[i] = new Item();
            curData[i] = new Item();
        }
        deepCopy(prevData[i], curData[i]);
        mapPad(raw, curData[i]);
    };

    var prevData = [];
    var curData = [];
    var Gamepad = {};
    window.Gamepad = Gamepad;
    Gamepad.getPreviousStates = function() {
        return prevData;
    };
    Gamepad.getStates = function() {
        var rawPads = getField()
        var len = rawPads.length;
        for (var i = 0; i < len; ++i) {
            mapIndividualPad(rawPads, i);
        }
        for (; i < curData.length; ++i) {
            prevData[i] = undefined;
            curData[i] = undefined;
        }
        return curData;
    };
    Gamepad.getPreviousState = function(i) {
        return prevData[i];
    };
    Gamepad.getState = function(i) {
        var rawPads = getField();
        mapIndividualPad(rawPads, i);
        return curData[i];
    };
    Gamepad.supported = getField() != undefined;


    // todo; These sort of seems like it could be data, but there's actually a
    // lot of exceptions, and it might be slower to map per frame anyway (we
    // want one of these methods to be hot for each connected device). Revisit
    // once we have more pads accounted for to see if there's consistent
    // patterns.

    var ChromeWindowsXinputGamepad = function(raw, into, index) {
        into.leftStickX = raw.axes[0];
        into.leftStickY = raw.axes[1];
        into.rightStickX = raw.axes[2];
        into.rightStickY = raw.axes[3];
        into.faceButton0 = raw.buttons[0];
        into.faceButton1 = raw.buttons[1];
        into.faceButton2 = raw.buttons[2];
        into.faceButton3 = raw.buttons[3];
        into.leftShoulder0 = raw.buttons[4];
        into.rightShoulder0 = raw.buttons[5];
        into.leftShoulder1 = raw.buttons[6];
        into.rightShoulder1 = raw.buttons[7];
        into.select = raw.buttons[8];
        into.start = raw.buttons[9];
        into.leftStickButton = raw.buttons[10];
        into.rightStickButton = raw.buttons[11];
        into.dpadUp = raw.buttons[12];
        into.dpadDown = raw.buttons[13];
        into.dpadLeft = raw.buttons[14];
        into.dpadRight = raw.buttons[15];
        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ee417001(v=vs.85).aspx
        into.deadZoneLeftStick = 7849.0/32767.0;
        into.deadZoneRightStick = 8689/32767.0;
        into.deadZoneShoulder0 = 0.5;
        into.deadZoneShoulder1 = 30.0/255.0;
    };

    var FirefoxWindowsXbox360Controller = function(raw, into, index) {
        // Wow, dinput is a disaster.
        into.leftStickX = raw.axes[0];
        into.leftStickY = raw.axes[1];
        into.rightStickX = raw.axes[3];
        into.rightStickY = raw.axes[4];
        into.faceButton0 = raw.buttons[0];
        into.faceButton1 = raw.buttons[1];
        into.faceButton2 = raw.buttons[2];
        into.faceButton3 = raw.buttons[3];
        into.leftShoulder0 = raw.buttons[4];
        into.rightShoulder0 = raw.buttons[5];
        into.leftShoulder1 = raw.axes[2] > 0 ? raw.axes[2] : 0;
        into.rightShoulder1 = raw.axes[2] < 0 ? -raw.axes[2] : 0;
        into.select = raw.buttons[6];
        into.start = raw.buttons[7];
        into.leftStickButton = raw.buttons[8];
        into.rightStickButton = raw.buttons[9];
        into.dpadUp = raw.axes[6] < -0.5 ? 1 : 0;
        into.dpadDown = raw.axes[6] > 0.5 ? 1 : 0;
        into.dpadLeft = raw.axes[5] < -0.5 ? 1 : 0;
        into.dpadRight = raw.axes[5] > 0.5 ? 1 : 0;
        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ee417001(v=vs.85).aspx
        into.deadZoneLeftStick = 7849.0/32767.0;
        into.deadZoneRightStick = 8689/32767.0;
        into.deadZoneShoulder0 = 0.5;
        into.deadZoneShoulder1 = 30.0/255.0;
    }

    var CommonMacXbox360Controller = function(raw, into, index) {
        // NOTE: Partial, doesn't set all values.
        into.leftStickX = raw.axes[0];
        into.leftStickY = raw.axes[1];
        into.faceButton0 = raw.buttons[0];
        into.faceButton1 = raw.buttons[1];
        into.faceButton2 = raw.buttons[2];
        into.faceButton3 = raw.buttons[3];
        into.leftShoulder0 = raw.buttons[4];
        into.rightShoulder0 = raw.buttons[5];
        into.select = raw.buttons[9];
        into.start = raw.buttons[8];
        into.leftStickButton = raw.buttons[6];
        into.rightStickButton = raw.buttons[7];
        into.dpadUp = raw.buttons[11];
        into.dpadDown = raw.buttons[12];
        into.dpadLeft = raw.buttons[13];
        into.dpadRight = raw.buttons[14];
        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ee417001(v=vs.85).aspx
        into.deadZoneLeftStick = 7849.0/32767.0;
        into.deadZoneRightStick = 8689/32767.0;
        into.deadZoneShoulder0 = 0.5;
        into.deadZoneShoulder1 = 30.0/255.0;
    }

    var ChromeMacXbox360Controller = function(raw, into, index) {
        CommonMacXbox360Controller(raw, into, index);
        into.rightStickX = raw.axes[3];
        into.rightStickY = raw.axes[4];
        into.leftShoulder1 = axisToButton(raw.axes[2]);
        into.rightShoulder1 = axisToButton(raw.axes[5]);
    };

    var ChromeMacLogitechF310Controller = function(raw, into, index) {
        into.leftStickX = raw.axes[0];
        into.leftStickY = raw.axes[1];
        into.faceButton0 = raw.buttons[1];
        into.faceButton1 = raw.buttons[2];
        into.faceButton2 = raw.buttons[0];
        into.faceButton3 = raw.buttons[3];
        into.leftShoulder0 = raw.buttons[4];
        into.rightShoulder0 = raw.buttons[5];
        into.select = raw.buttons[8];
        into.start = raw.buttons[9];
        into.leftStickButton = raw.buttons[10];
        into.rightStickButton = raw.buttons[11];

        // There is a switch to toggle the left joystick and dpad
        // only one is enabled at a time and the output always goes
        // through the left joystick
        into.dpadUp =  0;
        into.dpadDown = 0;
        into.dpadLeft = 0;
        into.dpadRight = 0;

        into.deadZoneLeftStick = 7849.0/32767.0;
        into.deadZoneRightStick = 8689/32767.0;
        into.deadZoneShoulder0 = 0.5;
        into.deadZoneShoulder1 = 30.0/255.0;
        console.log(raw.axes);
        into.rightStickX = raw.axes[2];
        into.rightStickY = raw.axes[5];
        into.leftShoulder1 = raw.buttons[6];
        into.rightShoulder1 = raw.buttons[7];
    };

    var FirefoxMacXbox360Controller = function(raw, into, index) {
        CommonMacXbox360Controller(raw, into, index);
        into.rightStickX = raw.axes[2];
        into.rightStickY = raw.axes[3];
        into.leftShoulder1 = axisToButton(raw.axes[4]);
        into.rightShoulder1 = axisToButton(raw.axes[5]);
    };

    var CommonMacPS3Controller = function(Raw, into, index) {
        // NOTE: Partial, doesn't set all values.
        into.leftStickX = raw.axes[0];
        into.leftStickY = raw.axes[1];
        into.rightStickX = raw.axes[2];
        into.faceButton0 = raw.buttons[14];
        into.faceButton1 = raw.buttons[13];
        into.faceButton2 = raw.buttons[15];
        into.faceButton3 = raw.buttons[12];
        into.leftShoulder0 = raw.buttons[10];
        into.rightShoulder0 = raw.buttons[11];
        into.leftShoulder1 = raw.buttons[8];
        into.rightShoulder1 = raw.buttons[9];
        into.select = raw.buttons[0];
        into.start = raw.buttons[3];
        into.leftStickButton = raw.buttons[1];
        into.rightStickButton = raw.buttons[2];
        into.dpadUp = raw.buttons[4];
        into.dpadDown = raw.buttons[6];
        into.dpadLeft = raw.buttons[7];
        into.dpadRight = raw.buttons[5];
    };

    var FirefoxMacPS3Controller = function(raw, into, index) {
        CommonMacPS3Controller(raw, into, index);
        into.rightStickY = raw.axes[3];
    };

    var ChromeMacPS3Controller = function(raw, into, index) {
        into.rightStickY = raw.axes[5];
    };

    var ChromeGenericController = function(raw, into, index) {
    into.leftStickX = raw.axes[0];
    into.leftStickY = raw.axes[1];
    into.rightStickX = raw.axes[3];
    into.rightStickY = raw.axes[2];
    into.faceButton0 = raw.buttons[0];
    into.faceButton1 = raw.buttons[1];
    into.faceButton2 = raw.buttons[2];
    into.faceButton3 = raw.buttons[3];
    into.leftShoulder0 = raw.buttons[4];
    into.rightShoulder0 = raw.buttons[5];
    into.leftShoulder1 = raw.buttons[7];
    into.rightShoulder1 = raw.buttons[6];
    into.select = raw.buttons[8];
    into.start = raw.buttons[9];
    into.leftStickButton = raw.buttons[10];
    into.rightStickButton = raw.buttons[11];
    into.dpadUp = raw.axes[5] < -0.5 ? 1 : 0;
    into.dpadDown = raw.axes[5] > 0.5 ? 1 : 0;
    into.dpadLeft = raw.axes[4] < -0.5 ? 1 : 0;
    into.dpadRight = raw.axes[4] > 0.5 ? 1 : 0;
   // From http://msdn.microsoft.com/en-us/library/windows/desktop/ee417001(v=vs.85).aspx
    into.deadZoneLeftStick = 7849.0/32767.0;
    into.deadZoneRightStick = 8689/32767.0;
    into.deadZoneShoulder0 = 0.5;
    into.deadZoneShoulder1 = 30.0/255.0;
};


    var active = [];
    // todo; possible we need to add different deadzones based on controller
    //       manufacturer, but perhaps they're fairly close anyway.
    if (isChrome && isWindows) {
        active.push([ 'Vendor: Unknown', 'Product: Unknown', ChromeGenericController, "Generic Controller" ]);
        active.push([ 'XInput ', 'GAMEPAD', ChromeWindowsXinputGamepad, "Xbox 360" ]);
    } else if (isChrome && isMac) {
        active.push([ 'Vendor: Unknown', 'Product: Unknown', ChromeGenericController, "Generic Controller" ]);
        active.push([ 'Vendor: 045e', 'Product: 028e', ChromeMacXbox360Controller, "Xbox 360" ]);
        active.push([ 'Vendor: 045e', 'Product: 02a1', ChromeMacXbox360Controller, "Xbox 360" ]);
        active.push([ 'Vendor: 054c', 'Product: 0268', ChromeMacPS3Controller, "Playstation 3" ]);
        active.push([ 'Vendor: 046d', 'Product: c216', ChromeMacLogitechF310Controller, "Logitech F310" ]);
    } else if (isFirefox && isWindows) {
        active.push([ 'Vendor: Unknown', 'Product: Unknown', ChromeGenericController, "Generic Controller" ]);
        active.push([ '45e-', '28e-', FirefoxWindowsXbox360Controller, "Xbox 360" ]);
        active.push([ '45e-', '2a1-', FirefoxWindowsXbox360Controller, "Xbox 360" ]);
        active.push([ '46d-', 'c21d-', FirefoxWindowsXbox360Controller, "Logitech F310" ]);
        active.push([ '46d-', 'c21e-', FirefoxWindowsXbox360Controller, "Logitech F510" ]);
    } else if (isFirefox && isMac) {
        active.push([ 'Vendor: Unknown', 'Product: Unknown', ChromeGenericController, "Generic Controller" ]);
        active.push([ '45e-', '28e-', FirefoxMacXbox360Controller, "Xbox 360" ]);
        active.push([ '54c-', '268-', FirefoxMacPS3Controller, "Playstation 3" ]);
    }



    Gamepad.magic = function(pad, mappings){
      var attachedGamepads = getField();
      if (attachedGamepads[0] || attachedGamepads[1] || attachedGamepads[2] || attachedGamepads[3]){
        
        for(m=0; m < mappings.length; m++){
          bindButtonToKey(pad, mappings[m][0], mappings[m][1]);
        }
      }  
    },
    bindButtonToKey = function(pad, myButton, myKey){
        if (myButton) {
          if( document.createEvent ) {
            var evObj = document.createEvent('Event');
            evObj.initEvent( 'keydown', true, false );;
            evObj.keyCode = myKey;
            window.dispatchEvent(evObj);
          } else if( document.createEventObject ) {
            console.log('createEventObject');
          }
        }
        else {
          if( document.createEvent ) {;
            var evObj = document.createEvent('Event');
            evObj.initEvent( 'keyup', true, false );;
            evObj.keyCode = myKey;
            window.dispatchEvent(evObj);
          } else if( document.createEventObject ) {
            console.log('createEventObject');
          }
        }
    }
});

1 decade ago by mimik

hello spacelime!
cool to see some fresh ideas.
You should add it to
pointofimpact.com

and also give people a headsup on the facebook group.
Think there is a google+ group aswell?

You should have a look at this compelling little library.
https://github.com/kallaspriit/HTML5-JavaScript-Gamepad-Controller-Library
Haven't tried it out on linux and mac yet but seams promising.
Page 1 of 1
« first « previous next › last »