Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to get analog joystick positions for proportional projects ? #23

Open
VigibotDev opened this issue Dec 9, 2020 · 8 comments
Open

Comments

@VigibotDev
Copy link

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

@alvaromontoro
Copy link
Owner

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?

@alvaromontoro
Copy link
Owner

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.

@VigibotDev
Copy link
Author

VigibotDev commented Dec 9, 2020

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

@VigibotDev
Copy link
Author

VigibotDev commented Dec 9, 2020

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!

@VigibotDev VigibotDev changed the title How to get analog axis value ? How to get analog-axis analog-value for proportional projects ? Dec 9, 2020
@VigibotDev VigibotDev changed the title How to get analog-axis analog-value for proportional projects ? How to get analog-axis positions for proportional projects ? Dec 9, 2020
@VigibotDev VigibotDev changed the title How to get analog-axis positions for proportional projects ? How to get analog joystick positions for proportional projects ? Dec 9, 2020
@alvaromontoro
Copy link
Owner

alvaromontoro commented Dec 9, 2020

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();
  }
});

@VigibotDev
Copy link
Author

VigibotDev commented Dec 18, 2020

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;

@VigibotDev
Copy link
Author

VigibotDev commented Dec 18, 2020

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;

@Make-It-Racing
Copy link

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 :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants