How to Use the HTML5 Gamepad API (with complete examples)
Tags: javascript, html
Published: 2020-12-15 22:30:29

---
title: "How to Use the HTML5 Gamepad API (with complete examples)"
published: true
description: "The HTML5 Gamepad API is one of the more exciting HTML5 APIs in my opinion. The API allows browser games and sites to take input from real game controllers connected to the user's machine. Hundreds of game controllers are supported, both wireless and wired, including Xbox One controllers, PS4 controllers, and more. In this article, I'll provide a full explanation of the many features that the Gamepad API offers, with examples in JavaScript. Information on browser support, gamepad button codes, taking input from the gamepad sticks, and more is included."
tags: #javascript, #js, #html
cover_image: "https://xtrp.io/api/content/static_files/how-to-use-the-html5-gamepad-api/photo_dev.jpg"

---

The HTML5 Gamepad API is one of the more exciting HTML5 APIs in my opinion. It allows a website to pretty easily take input from a game controller that is connected to the user’s machine. The API supports [hundreds of game controllers](https://gamepad-tester.com/codes), both wireless and wired, including Xbox One controllers and PS4 controllers to name a few.

Before we begin, note that **the gamepad API may not detect a gamepad until you press a button or move a stick on the controller.** So, make sure to press some of the buttons when you test any sites or programs that use the Gamepad API.

> Note: controllers and other game inputs are referred to as ‘gamepads’ throughout this article and in the gamepad API documentation.

## Checking if Your Gamepad is Connected and Troubleshooting Potential Issues

To check if your gamepad is successfully connected, run `navigator.getGamepads()` in the JavaScript console and check if the result has a Gamepad object, and is not an array of null elements.

If your gamepad isn’t working with the API, here are a few things to try:

 - check if the device is connected to your machine via bluetooth, USB, or other method
 - try restarting your computer or web browser
 - try pressing some of the buttons or moving one of the sticks on the controller so that it is detected
 - try closing any other games or apps that are using the gamepad

## Get a List of Connected Gamepads

The Gamepad API allows up to four gamepads to be connected at once.

To get an array of connected gamepads, use the `navigator.getGamepads()` method. The array is always of length four, where unused gamepad slots are `null`. The element(s) of connected gamepad(s) are `Gamepad` object(s). Here’s an example value of the `navigator.getGamepads()` method:

```javascript
console.log(navigator.getGamepads());
// --> [Gamepad Object, null, null, null]
// Here, only one gamepad is connected, and the other three gamepad slots are null.
```

> Before trying to use a the functionality of the Gamepad API, make sure a gamepad is connected using the instructions in the previous section.

## The `Gamepad` Object

The `Gamepad` object includes two important properties that are available in the vast majority of all gamepads and controllers: `buttons` and `axes`.

`axes` is an array of length four which represents the position of the left and right sticks in the gamepad. The first two elements in `axes` are the (x, y) coordinates of the position of the left stick, whereas the third and fourth elements in `axes` are the (x, y) coordinates of the position of the right stick. (x, y) values are numbers between -1 and 1 where the (0, 0) means the stick is has not moved.

In the horizontal axes (first and third elements in `axes`), `-1` would indicate the stick is moved fully to the left, and 1 would mean the stick is moved fully to the right. In the vertical axes (second and fourth elements in `axes`), `-1` would indicate the stick is moved fully to the top, and 1 would mean the stick is moved fully to the bottom. 

Here’s an example value of `axes` with explanations in the comments:

```javascript
setInterval(() => {
	const myGamepad = navigator.getGamepads()[0]; // use the first gamepad
	console.log(`Left stick at (${myGamepad.axes[0]}, ${myGamepad.axes[1]})` );
	console.log(`Right stick at (${myGamepad.axes[2]}, ${myGamepad.axes[3]})` );
}, 100) // print axes 10 times per second
```

Contrary to buttons in HTML, **event listeners cannot be added to gamepad buttons**. Instead, you can check if a button is currently pressed by using the boolean `pressed` property in the element in the `buttons` array.

Here’s a list of button indexes are their Xbox and PS4 Equivalents in the HTML5 Gamepad API:

| Index | Button `.pressed` Code      | Button on Xbox      | Button on PlayStation |
|-------|-----------------------------|---------------------|-----------------------|
| 0     | `gamepad.buttons[0].pressed`  | A                   | X                     |
| 1     | `gamepad.buttons[1].pressed`  | B                   | O                     |
| 2     | `gamepad.buttons[2].pressed`  | X                   | Square                |
| 3     | `gamepad.buttons[3].pressed`  | Y                   | Triangle              |
| 4     | `gamepad.buttons[4].pressed`  | LB                  | L1                    |
| 5     | `gamepad.buttons[5].pressed`  | RB                  | R1                    |
| 6     | `gamepad.buttons[6].pressed`  | LT                  | L2                    |
| 7     | `gamepad.buttons[7].pressed`  | RT                  | R2                    |
| 8     | `gamepad.buttons[8].pressed`  | Show Address Bar    | Share                 |
| 9     | `gamepad.buttons[9].pressed`  | Show Menu           | Options               |
| 10    | `gamepad.buttons[10].pressed` | Left Stick Pressed  | Left Stick Pressed    |
| 11    | `gamepad.buttons[11].pressed` | Right Stick Pressed | Right Stick Pressed   |
| 12    | `gamepad.buttons[12].pressed` | Directional Up      | Directional Up        |
| 13    | `gamepad.buttons[13].pressed` | Directional Down    | Directional Down      |
| 14    | `gamepad.buttons[14].pressed` | Directional Left    | Directional Left      |
| 15    | `gamepad.buttons[15].pressed` | Directional Right   | Directional Right     |
| 16    | `gamepad.buttons[16].pressed` | Xbox Light-Up Logo  | PlayStation Logo      |

Here's an example of checking if Button One (A on Xbox, X on PS4) is pressed:

```javascript
const myGamepad = navigator.getGamepads()[0]; // use the first gamepad

setInterval(() => { 
	console.log(`Is Button One Pressed? ${myGamepad.buttons[0].pressed}`);
}, 1000 / 10) // check 10 times per second if the button one is pressed
```

## Detect When a Gamepad Has Been Connected

The name of the event when a gamepad has been connected to the user’s machine is `gamepadconnected`. The event argument that is passed into the event function includes a `gamepad` property, which is a `Gamepad` object for the gamepad the has been connected.

Instead of accessing this gamepad directly, it is more common to get the index of this gamepad in the `navigator.getGamepads()` array by using the `Gamepad.index`. For example:

```javascript
// global gamepad object
let gamepadIndex;
window.addEventListener('gamepadconnected', (event) => {
	gamepadIndex = event.gamepad.index;
});

// now print the axes on the connected gamepad, for example: 
setInterval(() => {
	if(gamepadIndex !== undefined) {
		// a gamepad is connected and has an index
		const myGamepad = navigator.getGamepads()[gamepadIndex];
		console.log(`Left stick at (${myGamepad.axes[0]}, ${myGamepad.axes[1]})` );
		console.log(`Right stick at (${myGamepad.axes[2]}, ${myGamepad.axes[3]})` ); 
	}
}, 100) // print axes 10 times per second
```

## A More Complicated Example

Here's an example program that displays which buttons on a controller are pressed at a given time. Try running this code and pressing buttons on your gamepad; you should see that the indexes of the buttons that are pressed is displayed.

```html
<body>
	<h1>No Controller Connected</h1>
</body>

<script type="text/javascript">
// global gamepad object
let gamepadIndex;
window.addEventListener('gamepadconnected', (event) => {
	gamepadIndex = event.gamepad.index;
});

setInterval(() => {
	if(gamepadIndex !== undefined) {
		// a gamepad is connected and has an index
		const myGamepad = navigator.getGamepads()[gamepadIndex];
		document.body.innerHTML = ""; // reset page
		myGamepad.buttons.map(e => e.pressed).forEach((isPressed, buttonIndex) => {
			if(isPressed) {
				// button is pressed; indicate this on the page
				document.body.innerHTML += `<h1>Button ${buttonIndex} is pressed</h1>`;
			}
		})
	}
}, 100) // print buttons that are pressed 10 times per second
</script>
```

## Browser Support

The HTML5 Gamepad API has complete support in most modern web browsers today. However, there are a few browsers that don't yet support it as of December 2020, including:

 - IE (11)
 - Opera Mini
 - Opera Mobile
 - Android Browser
 - KaiOS Browser

For more up-to-date information on browser support, see the [Gamepad API's CanIUse Page](https://caniuse.com/gamepad).

To check if the browser supports the Gamepad API in JavaScript, the following code can be used:

```javascript
const hasGamepadAPI = () => "getGamepads" in navigator;
```

## Conclusion

I hope this helps in learning how to use the HTML5 Gamepad API. While the API is not yet widely used in online games at the moment, it can still be useful for a number of projects and can be fun to try out.

Thanks for scrolling.

*&mdash; Gabriel Romualdo, December 15, 2020*