Menu Home

Gamepad

Hi everyone, and welcome to another exciting edition of Boring JavaScript. Today, we’re going to have a little fun with the browser’s API and take a look at the Gamepad interface. This let’s us connect a Gamepad to our pc and control objects on the screen. Yes, even YOU can turn your PC into an X-Box or PS5 or Nintendo – if you have the millions of research dollars and a bunch of really smart people. But it will work great for your indie projects.

Don’t like to read? Then watch our video.

A Button Here, a Axes There

Programming for a gamepad is very simple, but there are two pieces you need to keep in mind. The first is how to access the gamepad itself. It’s done with code like this:

let gamepadIndex;

const gamepadConnected = (event) => {
	gamepadIndex = event.gamepad.index;
	requestAnimationFrame(updateTable);
};

const gamepadDisconnected = (event) => {
	domConnected.textConent = "No";
};

window.addEventListener("gamepadconnected", gamepadConnected);
window.addEventListener("gamepadconnected", gamepadDisconnected);

And that’s it!

Nothing happens until at least one controller activates some button somewhere on the controller, at which point the ‘gamepadConnected’ event fires, and you can capture the index of the gamepad from the ‘index’ property.

You will receive this event each time a new controller connects to your computer (usually upon pressing a button). While the code above only saves the first one (for demo purposes – and my computer only has one controller!), in normal operations you would have to assume that you have multiple controllers and handle it according.

However, notice Line 5 – ‘requestAnimationFrame’. That is a very important part of this routine. Why?

It’s Not Gaming Animation

Normally, when listening for events inside the browser, you use ‘addEventListener’ – for example:

document.addEventListener('click', (event) => console.log(event));

… will fire the ‘console.log’ each time there is a mouse click somewhere on the document.

Gamepads do not work this way, though. You can press the buttons or move the axes all day long and you’ll never get anything. You must constantly poll your system in order to find out what’s been pressed or moved. And since doing polling loops in JavaScript can cause your browser to lock up if you’re not careful, what can we do about it?

JavaScript gives you a nice and convenient method to do just that – and it’s called ‘requestAnimationFrame’. That will tell JavaScript to run a specified function during it’s normal internal paint polling cycle. Meaning, that it will put that routine onto it’s stack to be executed at the next available time slot.

And that’s it. You don’t have to worry about looping or polling or anything. JavaScript will take care of that for you. Let’s revisit to code above and add in our routine.

let gamepadIndex;

const gamepadConnected = (event) => {
	gamepadIndex = event.gamepad.index;
	requestAnimationFrame(updateTable);
};

const gamepadDisconnected = (event) => {
	domConnected.textConent = "No";
};

const updateTable = () => {
	const gamepad = navigator.getGamepads()[gamepadIndex];
    // gamepad.buttons contains true/false settings
    // gamepad.axes contains values from -1.0 to 1.0 for the sticks
    // from here, you can do whatever you want. In the video, we display everything on a table
	requestAnimationFrame(updateTable);
}

window.addEventListener("gamepadconnected", gamepadConnected);
window.addEventListener("gamepadconnected", gamepadDisconnected);

Now we have the ‘updateTable’ method, which, in the video, will update the table we display on the screen. Inside ‘updateTable’, we first get to our connected gamepad via the ‘getGamepads()’ method (Line 13). This will return an array of gamepads connected (and not connected) to the system. Any gamepad not connected to the system will have a ‘null’ value in that gamepad slot in the getGamepads() array.

Notice Line 17. We need to again do the ‘requestAnimationFrame’ call. Why? The routine doesn’t actually poll on an ongoing basis – it only requests one frame within the internal polling system. Therefore, we will need to continually request frames from JavaScript in order to get this to work properly.

And don’t worry about speed. ‘requestAnimationFrame’ is used in browser-based games all the time, and even with gamepads and graphics, can still get 60fps.

The Video

Here is a video on the subject:

Shameless Plug

Check us out everywhere!

Check out all our videos at: https://www.boringjavascript.com

Check out everything at: https://www.thevirtuoid.com

Facebook: https://www.facebook.com/TheVirtuoid

Twitter: https://twitter.com/TheVirtuoid

YouTube: https://www.youtube.com/channel/UCKZ7CV6fI7xlh7zIE9TWqgw

Categories: Boring JavaScript Javascript

Tagged as:

thevirtuoid

Web Tinkerer. No, not like Tinkerbell.

Creator of the game Virtuoid. Boring JavaScript. Visit us at thevirtuoid.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: