npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-gamepads

v1.0.0

Published

A set of hooks and utilities for using the Gamepad API inside React

Downloads

6,785

Readme

react-gamepads 🕹🎮

A set of hooks and utilities for using the Gamepad API inside React. Use a hook, get access to gamepad input -- it's that easy.

🚀 Getting Started

yarn add react-gamepads

Now you just pick: hooks or context? 👇🏼

useGamepads Hook

With this hook you can have a component subscribe to all gamepad input. This allows you to have a component "react" to gameplay input as it's received.

In this example, we take the input and set the component's state to it. This lets you use the state inside the component and have it change. You could also store it inside a "ref" (with useRef) if preferred.

import React, { useState } from 'react';
import { useGamepads } from 'react-gamepads';

export default function App() {
  const [gamepads, setGamepads] = useState({});
  useGamepads(gamepads => setGamepads(gamepads));

  return <div>{gamepads[0].buttons[4].pressed}</div>;
}

Hooks are a great way of quickly bringing gamepad input to any component. You could also use this to create a single "controller" component that handles all input across the app (like a <GameController buttonOne={() => yourFunc} />) -- see react-gamepad for an example of this.

<GamepadsProvider> Context

With context, you can have parts (or the entire app) get "provided" all gamepad input, and subscribe to the data using a context consumer.

  1. First, wrap the app in the provider:
import React from 'react';

import { GamepadsProvider } from 'react-gamepads';

export default function App() {
  return <GamepadsProvider>Your app</GamepadsProvider>;
}
  1. Then you can use the context in another component with useContext():
import React, { useContext, useLayoutEffect, useState } from 'react';
import { GamepadsContext } from '../context/GamepadsContext';

const GameInput = () => {
  const { gamepads } = useContext(GamepadsContext);

  return <div>{gamepads[0].buttons[0].pressed}</div>;
};

export default GameCursor;

2a. Or you can use a context consumer component, which provides the gamepad data as a "render prop":

<GamepadsContext.Consumer>
  {({ gamepads }) => {
    return <div>{gamepads[0].buttons[0].pressed}</div>;
  }}
</GamepadsContext.Consumer>

Context is great for providing sections of the app with gamepad input and isolate the state inside the context -- rather than having multiple components subscribed (like the hook -> state example).

Debugging Gamepad Input

When working on apps with gamepad input, it helps to visualize the input.

You can quickly print out all buttons using this code:

import React, { useState } from 'react';
import { useGamepads } from 'react-gamepads';

export default function App() {
  const [gamepads, setGamepads] = useState({});
  useGamepads(gamepads => setGamepads(gamepads));

  const gamepadDisplay = Object.keys(gamepads).map(gamepadId => {
    // console.log("displaying gamepad", gamepads[gamepadId]);
    return (
      <div>
        <h2>{gamepads[gamepadId].id}</h2>
        {gamepads[gamepadId].buttons &&
          gamepads[gamepadId].buttons.map((button, index) => (
            <div>
              {index}: {button.pressed ? 'True' : 'False'}
            </div>
          ))}
      </div>
    );
  });

  return (
    <div className="Gamepads">
      <h1>Gamepads</h1>
      {gamepadDisplay}
    </div>
  );
}

Or you can use the <GamepadController> component to see a controller. This will display the specified controller's input, and you can optionally provide styling (like fixing it to a corner of the screen):

<GamepadController
  controller={1}
  style={{ position: 'fixed', bottom: 0, right: 0 }}
/>

📦 Examples

Here are some examples to get you started using this library and get those creative juices pumping ⚡️🧠💡

🖱 Game Cursor

This is a simple example of using the analog sticks and directional pad to move a cursor around the screen. You can also press a button to change the cursor color. It uses framer-motion under the hood to smoothly animate the cursor. Keep in mind this does not check for the edges of the screen.

Browse and run the code using CodeSandbox

🗄 Menu

This is an example of using controller input to navigate an HTML menu. You can press the up or down buttons on the directional pad to change the active item of the menu. Pressing a button "clicks" the link, navigating to the selected route.

Browse and run the code using CodeSandbox

🐎 Horse Game

This is a simple game based on the "Horse Stance" mini-game from Shenmue 3. It features a "Game Start" screen with a "Press any button" example, game input using analog sticks and directional pad, and other basic game design techniques. The goal of the game is to keep the "position" at or around 500, which gives you the highest score.

Browse and run the code using CodeSandbox

🛠 Development

  1. Install dependencies: yarn
  2. Compile TS to JS with hot reloading: yarn watch

Want to test development inside another React project? Try using npm link to symlink the local package to your test React app.

Commits

  1. Stage your changes: git add .
  2. Commit using the Commitzen CLI: yarn commit

This will walk you through the process of writing the proper syntax for semantic release.

Make sure to lint your work before your try committing. The commit process runs linting, and if it fails it will fail your commit, forcing you to write it over again.

Release

  1. Install: yarn
  2. Build: yarn build
  3. Release: yarn semantic-release
  4. Publish: npm publish

Ideally this should be handled by the CI/CD. There is a Github Actions workflow that handles most of this, minus the NPM publish.

📚 Credits / References