gamecontroller.js
gamecontroller.js copied to clipboard
How to get analog joystick positions for proportional projects ?
Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
I need to read X / Y values of joystick
Describe the solution you'd like A clear and concise description of what you want to happen.
An analog axis move event
Right now the library is "reactive": if the user sets a function for an event, it will trigger it when the event happens. For example, you can set functions for "up", "right", "down", or "left" that will be triggered when the first analog axis moves (you can listen to the different analogs by using up0, up1,...)
// examples
gamepad.on('left', characterGoLeft);
gamepad.on('right', characterGoRight);
gamepad.on('button0', characterJump);
Is that what you want?
I have a plan to revamp the library so it is more "proactive": if an event happens, it will trigger a custom event and the user can listen to it. That way, the notation will be less jQuery-looking and more native-JS-looking (keeping both methods for a while). But that won't happen in the short term.
I want to add the Joystick support for a robotic web remote : https://www.vigibot.com/ It's a 100% free non lucrative project to make low latency FPV piloting over the internet. gamecontroller.js look awesome because there is some browser to browser difference inside gamepad API. I need to read analog value from sticks and let's any user to make own channel assign. For now keyboard, mouse and touchpad are supported. Sorry for my english
I don't think your answer is for proportional analog values / joystick positions I need for my project :( Some robot are very powerful and high torque, starting at 100% full power are dangerously to fast for them. We use flying drone also need proportional piloting you can't fly a drone with keyboard like inputs!
I think I see the problem now: the way it is right now, the direction/joystick is triggered or not, it doesn't take into account the actual value, just the threshold, then it's all in or nothing at all. Is that the issue?
If it is, we could update the callback for the axes, so it includes the "force" as a [0..1] value. That way you know if the joystick was moved AND how much. (e.g., 0.5 would be half strength, 1.0 would be full strength). Would that work? That way, you could do something like this:
// example
gamepad.on('left', function(value) {
if (value < 0.5) {
moveCharacterLeftSlow();
} else if (value < 0.9) {
moveCharacterLeftNormal();
} else {
moveCharacterLeftFast();
}
});
Looks OK, so far I've used the native gamepad API and developed a user-configurable abstraction layer myself. I even made a configurable dead zone like this. Here is the "analog" part I required when I opened this ticket
function deadzone(n) {
if(n > prefs.GAMEPADDEADZONE)
n -= prefs.GAMEPADDEADZONE;
else if(n < -prefs.GAMEPADDEADZONE)
n += prefs.GAMEPADDEADZONE;
else
n = 0;
n *= 1 / (1 - prefs.GAMEPADDEADZONE);
return n;
}
let gamepads = navigator.getGamepads();
let gamepad = gamepads[prefs.GAMEPADINDEX];
if(!gamepad)
return;
let axes = [0, 0, 0, 0];
for(let i = 0; i < gamepad.axes.length; i++)
axes[i] = deadzone(gamepad.axes[i]);
let gamepadJoy1 = axes[0] || axes[1]
if(gamepadJoy1)
// transmit axes[0] * 127, axes[1] * 127
else if(oldGamepadJoy1)
// transmit 0, 0
oldGamepadJoy1 = gamepadJoy1;
I think I have all the "Button" functionality of your lib in this. I give you all my work extracted from my project.
User gamepad button mapping (multiple buttons for one function is OK) JSON config object :
{
"GAMEPADINDEX": 0,
"GAMEPADDEADZONE": 0.1,
"GAMEPADGAINX16": 20,
"GAMEPADGAINY16": 20,
"GAMEPADMAP": {
"Left": [],
"Forward": [12],
"Right": [],
"TurnLeft": [14],
"Backward": [13],
"TurnRight": [15],
"PreviousTool": [8],
"ResetTools": [6, 7],
"NextTool": [9],
"IncrementLeft": [],
"IncrementForward": [],
"IncrementRight": [],
"IncrementTurnLeft": [],
"IncrementBackward": [],
"IncrementTurnRight": [],
"Brake": [],
"Boost": [4],
"EasyNextTool": [5],
"Switch0": [0],
"Switch1": [1],
"Switch2": [2],
"Switch3": [3],
"Switch4": [],
"Switch5": [],
"Switch6": [],
"Switch7": [],
"Sleep": [],
"VideoCapture": []
}
}
Initialization (once) :
let gamepadButtonsPressed = [];
let gamepadMap;
function initGamepadMap() {
gamepadMap = {};
$.each(prefs.GAMEPADMAP, function(fonction, boutons) {
$.each(boutons, function(i, bouton) {
gamepadMap[bouton] = fonction;
});
});
}
initGamepadMap();
Event loop to get DOWN and UP event for any gamepad button on any browser (tested on chrome firefox ...) :
for(let i = 0; i < gamepad.buttons.length; i++) {
if(gamepad.buttons[i].pressed && !gamepadButtonsPressed[i]) {
let action = gamepadMap[i];
switch(action) { // I have more case on my code. START (BUTTON UP) part
case undefined:
break;
default:
let start = conf.ACTIONS[action].START; // Another abstraction layer you can remove
if(start)
txCommandeStart(start); // Transmit command START (BUTTON UP)
}
} else if(!gamepad.buttons[i].pressed && gamepadButtonsPressed[i]) {
let action = gamepadMap[i];
switch(action) { // I have more case on my code STOP (BUTTON DOWN) part
case undefined:
break;
default:
let stop = conf.ACTIONS[action].STOP; // Another abstraction layer you can remove
if(stop)
txCommandeStop(stop); // Transmit command STOP (BUTTON DOWN)
}
}
gamepadButtonsPressed[i] = gamepad.buttons[i].pressed;
Hi! I am also in need to find out where the joystick is located and not only weather it was pressed or not... Is there any way to achieve this with the library? Or can you point me in the correct direction?
Thanks :-)