Giter VIP home page Giter VIP logo

gamecontroller.js's Introduction

gameController.js

A JavaScript library that lets you handle, configure, and use gamepad and controllers on a browser.

Build Status npm npm

Getting started

GameController.js is a lightweight library (~6KB) that uses JavaScript and the standard Gamepad API, and does not have any plugin/library dependencies.

Installation

From npm:

npm i gamecontroller.js

From yarn:

yarn add gamecontroller.js

Directly into your webpage (check latest release on github):

<script src="./gamecontroller.min.js"></script>

Usage

After importing the library into your webpage/project, gameControl will be available to use. This object comes with a series of properties and methods that will allow to handle the different gamepads connected to the computer.

The connected gamepads will be stored in a list of gamepad objects in gameControl. This gamepad object is not the default one returned by the browser but a higher-level interface to interact with it and simplify its usability.

Once the file is imported into the project, the object gameControl will be available and ready to be used.

gameControl.on('connect', function(gamepad) {
  gamepad.on('up', moveCharacterUp);
});

Visit the Wiki for a full list of the properties, methods and events of these two objects.

Events for gameControl

For the object gameControl, events are associated using the .on() method:

gameControl.on('connect', gamepad => {
  console.log('A new gamepad was connected!');
});

Here is a list of the events that can be associated using .on():

Name Description
connect Triggered every time that a gamepad is connected to the browser. It returns an instance of the `gamepad` object described below.
disconnect Triggered when a gamepad is disconnected from the browser.
beforeCycle Triggered before the gamepads are checked for pressed buttons/joysticks movement (before those events are triggered).
afterCycle Triggered after the gamepads are checked for pressed buttons/joysticks movement (after those events have been triggered).

Events for gamepad

The events for the gamepad objects work a little bit different. The event name, is the name of the button/direction that was activated (e.g. button0, up, etc.) And there are three functions that can be used to associate event handlers for them in different situations:

  • .on(): triggered every cycle, while the button/joystick is pressed/active.
  • .before(): triggered the first cycle that a button/joystick is pressed.
  • .after(): triggered the first cycle after a button/joystick stopped being pressed.

All three functions can be chained and allow two parameters: the first one is the button/direction that was activated, and the second parameter is the callback function. Example:

gamepad.on('button0',     () => { console.log('Button 0 still pressed...'); })
       .before('button0', () => { console.log('Button 0 pressed...');       })
       .after('button0',  () => { console.log('Button 0 was released';      });

To see the event flow and how the different events are lined-up and interact with each other, visit the Event Flow wikipage.

Thisus

These are the events that can be passed as first parameter to the event functions:

Name Description
button0 Triggered when button 0 is pressed.
button1 Triggered when button 1 is pressed.
button2 Triggered when button 2 is pressed.
button3 Triggered when button 3 is pressed.
button4 Triggered when button 4 is pressed.
button5 Triggered when button 5 is pressed.
button6 Triggered when button 6 is pressed.
button7 Triggered when button 7 is pressed.
button8 Triggered when button 8 is pressed.
button9 Triggered when button 9 is pressed.
button10 Triggered when button 10 is pressed.
button11 Triggered when button 11 is pressed.
button12 Triggered when button 12 is pressed.
button13 Triggered when button 13 is pressed.
button14 Triggered when button 14 is pressed.
button15 Triggered when button 15 is pressed.
button16 Triggered when button 16 is pressed.
up0 Triggered when the first axe/joystick is moved up.
down0 Triggered when the first axe/joystick is moved down.
right0 Triggered when the first axe/joystick is moved right.
left0 Triggered when the first axe/joystick is moved left.
up1 Triggered when the second axe/joystick is moved up.
down1 Triggered when the second axe/joystick is moved down.
right1 Triggered when the second axe/joystick is moved right.
left1 Triggered when the second axe/joystick is moved left.
start Triggered when Start button is pressed.
This is an alias for event button9.
select Triggered when Select button is pressed.
This is an alias for event button8.
power Triggered when Power button is pressed (e.g. the Xbox logo in an Xbox controller).
This is an alias for event button16.
l1 Triggered when the left back button 1 is pressed.
This is an alias for event button4.
l2 Triggered when left back button 2 is pressed.
This is an alias for event button6.
r1 Triggered when right back button 1 is pressed.
This is an alias for event button5.
r2 Triggered when right back button 2 is pressed.
This is an alias for event button7.
up Triggered when the main/first axe/joystick is moved up.
This is an alias for event up0.
down Triggered when the main/first axe/joystick is moved down.
This is an alias for event down0.
right Triggered when the main/first axe/joystick is moved right.
This is an alias for event right0.
left Triggered when the main/first axe/joystick is moved left.
This is an alias for event left0.

These names are not arbitrary. They match the buttons and axes described in the W3C Gamepad API specicification:

https://github.com/alvaromontoro/gamecontroller.js/blob/master/public/gamepad.svg

Browser Support

Edge Logo 32x32
Edge
Firefox Logo
Firefox
Chrome
Chrome
Safari Logo
Safari
Opera logo
Opera
12+ 29+ 25+ 10.1+ 24+

Examples

The examples folder contains different examples to showcase how to use the library:

  • Connectivity: shows how to detect if a gamepad was connected/disconnected.
  • Buttons and Joysticks: see how the buttons from your gamepad map to the default gamepad.
  • SNES Controller: replica of a SNES controller (based on a previous CodePen demo).
  • Alvanoid: small Arkanoid-based game (based on a previous CodePen demo).
  • Pong: multiplayer demo with the classic game Pong for 2 players on 2 gamepads.

gamecontroller.js's People

Contributors

alvaromontoro avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

gamecontroller.js's Issues

Add after actions to axes/joystick

After actions will be triggered after a button/joystick goes from active mode to deactivated mode (when the user releases the button/joystick).

Published package broken

Describe the bug
The main property in package.json points at dist/index.js, but no such file exists in the latest published release; rather, it's dist/gamecontroller.js.

To Reproduce
Steps to reproduce the behavior (include code to replicate if possible):

  1. npm install gamecontroller.js
  2. `require("gamecontroller.js")

Expected behavior
Should load correctly; produces a MODULE_NOT_FOUND error instead.

Screenshots
N/A

Desktop (please complete the following information):
N/A

Additional context
N/A

Create mapping option

Is your feature request related to a problem? Please describe.
Right now, if the gamepad is not "standard", the developers have to create their own mapping functionality manually, which is not ideal.

Describe the solution you'd like
Provide developers with an internal functionality to remap buttons/axes.

Describe alternatives you've considered
Create a mapping array/object, and allow developers to set it up. They will still have to figure out a way to display to the user the mapping selection. But once it's done, passing the new mapping array/object should internally fix the mapping.

Add default values for gamepad

If the gamepad api fails or during testing, when the api is not available, the library crashes because there's no fallbacks.

Add default/fallback values so testings can be created to gamepad.

Delay before repeat (ala keypress repeat delay)

Is there a simple way of implementing a hold delay, such that the following behavior happens:

  1. On button press: single event,
  2. then if held an X ms delay before it repeats.

Similar to a keyboard repeat delay. TIA.

Name of gamepad and return obj on disconnect event

Hi, In future pls add gamepad name variable
for example: I added in init: function
name: t.id,
And on disconnected event i return obj this.onDisconnect(e)
In some cases, it is needed for notifications, which gamepad was connected or disconnected
thank!

Add sensitivity option for joystick/axes

Add a setting to specify how sensitive the joystick needs to be. And use it to trigger the directional events.

The value can go from 0 to 1 (or negative depending on direction). And the threshold is hardcoded to 1.

Allow developers to specify a lower value.

Refactor the code

The code si growing considerably and there are different opportunities to clean, and reduce it while improving maintainability

Can't get it working

Describe the bug
I am using the code:

gameControl.on('connect', function(gamepad) {
    gamepad.on('button0', console.log('up'));
});

and all it prints in the console is

[Info] Gamepad detected. (gamecontroller.min.js, line 1)
[Log] up (index.js, line 2)
[Error] TypeError: this.buttonActions[e].action is not a function. (In 'this.buttonActions[e].action()', 'this.buttonActions[e].action' is undefined)
	checkStatus (gamecontroller.min.js:1:2758)
	checkStatus (gamecontroller.min.js:1:5839)

To Reproduce
My code is:
index.html

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]>      <html class="no-js"> <!--<![endif]-->
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
    </head>
    <body>
        <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
        <script src="gamecontroller.min.js"></script>
        <script src="index.js" async defer></script>
        <p id="gamepadInfo"></p>
    </body>
</html>

index.js

gameControl.on('connect', function(gamepad) {
    gamepad.on('button0', console.log('up'));
});

Expected behavior
Print 'up' when the A button is pressed

Desktop (please complete the following information):

  • OS: macOS Big Sur
  • Browser: Safari
  • Version: Safari 14.0.3

Disconnect event not work with a second gamepad

Hi,I find another issue,
Connect event work fine with multiple gamepads, but
If i disconnect second gamepad, event not call.
Disconnect event work only with first gamepad (e.id 0) ,Its a bug ?
Also if i reconnect second gamepad, event connect not call , but buttons work fine

Add touchstart/touchend events

Touchstart/touchend events are triggered when the user places their fingers on top of the button/joystick, or moves them out.

It is a property of the Gamepad API, but it is not available in all joysticks. So don't worry if the results may be choppy.

Then new event names will be the same that we have, adding "touchstart" and "touchend" at the end of it. E.g.: button0touchstart, button0touchend, etc.

Add property with axes values

Add a property to the gamepad class that holds the values for all the axes/joysticks.

This property with be an object/array with tuples (horizontal-vertical) for each axe/joystick, that will be updated every cycle before the button events are triggered.

Set axeThreshold Not work

Hi, I tried to change axeThreshold as it is said in the documentation
gameControl.set('axeThreshold', 0.5);
In console log i see the axeThreshold is set to 0.5, but analogs stop work (i use xbox one and PS4 controllers)
If i change axeThreshold:[0.5] var manually inside the library , its work fine

Event Flow wikipage does not exist

Reference to the "Event Flow wikipage" in the Events section of documentation points nowhere. The page labeled "Events" does not describe anything different than the page from which "Event Flow wikipage" is referenced (main API docs / readme)

Improve npm integration

Right now, when the project is built and published into npm, the whole project is submitted there. The goals of this ticket are to:

  • Verify the npm publication.
  • Make the needed adjustments so only what is needed is published.
  • Clean the related code.

[Feature Request] Pausing a gamepad

Would be nice to have a way to pause a gamepad, e.g.

gamepad.on('button0', doSomething())

window.addEventListener('blur', () => {
  // the window lost focus
  gamepad.pause()
})

window.addEventListener('focus' () => {
  // the window focused back
  gamepad.resume()
})

I run into a problem where a webapp (that uses the controller) continues to react to gamepad controller when it is minimized (and when I use the controller in another app or game). It would be useful in that scenario.
But think about this another use-case also during a cutscene you want to "shut down" your gamepad.

This is a temporary "hack" I am using:

let _gamepad, buttonActions, axesActions;

// Creating maps with ghost functions
const silentButtonActions = {
  0: { action: () => {}, before: () => {}, after: () => {} },
  1: { action: () => {}, before: () => {}, after: () => {} },
  2: { action: () => {}, before: () => {}, after: () => {} },
  3: { action: () => {}, before: () => {}, after: () => {} },
  4: { action: () => {}, before: () => {}, after: () => {} },
  5: { action: () => {}, before: () => {}, after: () => {} },
  6: { action: () => {}, before: () => {}, after: () => {} },
  7: { action: () => {}, before: () => {}, after: () => {} },
  8: { action: () => {}, before: () => {}, after: () => {} },
  9: { action: () => {}, before: () => {}, after: () => {} },
  10: { action: () => {}, before: () => {}, after: () => {} },
  11: { action: () => {}, before: () => {}, after: () => {} },
  12: { action: () => {}, before: () => {}, after: () => {} },
  13: { action: () => {}, before: () => {}, after: () => {} },
  14: { action: () => {}, before: () => {}, after: () => {} },
  15: { action: () => {}, before: () => {}, after: () => {} },
  16: { action: () => {}, before: () => {}, after: () => {} },
}

const silentAxesActions = {
  0: {
    up: { action: () => {}, before: () => {}, after: () => {} },
    right: { action: () => {}, before: () => {}, after: () => {} },
    down: { action: () => {}, before: () => {}, after: () => {} },
    left: { action: () => {}, before: () => {}, after: () => {} },
  },
  1: {
    up: { action: () => {}, before: () => {}, after: () => {} },
    right: { action: () => {}, before: () => {}, after: () => {} },
    down: { action: () => {}, before: () => {}, after: () => {} },
    left: { action: () => {}, before: () => {}, after: () => {} },
  }
}

/* When the gamepad connects */
gameControl.on('connect', (gamepad) => {
  // get a global reference
  _gamepad = gamepad
  
  gamepad
    .on(...)
})



/* When the window loses focus, we should prevent game inputs */
window.addEventListener('blur', () => {
  pauseGamepad()
})
/* When the window gets the focus back */
window.addEventListener('focus', () => {
  resumeGamepad()
})


function pauseGamepad() {
  if (_gamepad) {
    // save for later
    buttonActions = _gamepad.buttonActions
    axesActions = _gamepad.axesActions

    // silence actions
    _gamepad.buttonActions = silentButtonActions
    _gamepad.axesActions = silentAxesActions
  }
}
function resumeGamepad() {
  if (_gamepad) {
    _gamepad.buttonActions = buttonActions
    _gamepad.axesActions = axesActions
  }
}

As you can see this is a bit nasty to implement and you have to think implementing that every time a new gamepad is detected.

Note: If you will accept the "Migrate to TypeScript" PR that was proposed to you, I may be able to check the code and propose another PR for that (worth my time).

Add after actions to buttons

After actions will be triggered after a button/joystick goes from active mode to deactivated mode (when the user releases the button/joystick).

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.