Socket
Socket
Sign inDemoInstall

universal-game-controller

Package Overview
Dependencies
0
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    universal-game-controller

Simple game input for touch screen, keyboard, gamepad and mouse


Version published
Weekly downloads
4
Maintainers
1
Install size
16.6 kB
Created
Weekly downloads
 

Readme

Source

Universal Game Controller

npm npm bundle size NPM

Simple game input for 💻 keyboard, 📱 touchscreen and 🎮 gamepad through a unified API. Made for game jams.

Why?

  • You’ll need keyboard support for maximum game development speed and compatibility.
  • However, actual gameplay will be more fun and impressive with a game controller. Only if you had the time...
  • Touchscreen support will make it 100x easier to show the game to your friends after the game jam.

How?

Current game inputs are:

  • one joystick
  • one button

Constraining? That’s where creativity starts! Never underestimate the power of simplicity – easy to learn is easy to love.

Demo: https://ugc.bloat.app

See importing instructions below.

Design goals

  • Fun and practical to use in game jams.
  • Games are equally playable on laptop (for development), TV (for immersion) and phone (for sharing).
  • Easy to use for new players (on all platforms).
  • Fun even at high skill levels (on all platforms).
  • Light-weight and zero dependencies.

Features

All user inputs are provided as a state of the controller – no events as of now. These are meant to be read in the game update loop.

Joystick

controller.move: { x, y }

  • Output is a 2D vector that is guaranteed to be inside the unit circle (even if multiple controllers are used at once).
  • Gamepad: Analog left joystick (with a dead zone for drift compensation).
  • Keyboard: WASD (with diagonal length compensation).
  • Touchscreen: The first touch (anywhere) can be slided around as a virtual joystick. Scrolling the page is disabled (also on Safari).
  • Should be exactly (0, 0) when the user is not touching the controls – however, this is not guaranteed for gamepad, since the neutral position might vary from device to device, and there is no specification for maximum allowed drift.

Trigger button

controller.trigger: boolean

  • Gamepad: Button 1 (Xbox: A, Switch: B)
  • Keyboard: Space. Scrolling is prevented.
  • Touchscreen: Second touch (anywhere). The button is sustained even if the first touch ends.

Controller type

controller.type: InputType

  • The game can display instructions for the specific input device that the player is using.
  • If a gamepad is connected, type is always gamepad.
  • Otherwise touchscreen and keyboard will switch to the one that had the last input event.
  • On page load before any user actions, type is touchscreen if a touchscreen is present.

Importing

URL

<script src="https://cdn.jsdelivr.net/npm/universal-game-controller@1.3.2/dist/main.js"></script>
const { controller } = UniversalGameController

NPM

npm install universal-game-controller
import { controller } from 'universal-game-controller'

Example using URL import

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="https://cdn.jsdelivr.net/npm/universal-game-controller@1.3.2/dist/main.js"></script>
    </head>
    <body>
        <div id="instructions" style="font-family: sans-serif; width: 100%; text-align: center; font-size: 2em; padding-top: 0.3em;"></div>
        <div id="container" style="border: 2vmin solid rgb(15, 31, 46); width: 80vmin; height: 80vmin; border-radius: 50%; position: absolute; left: calc(50% - 40vmin); top: calc(50% - 40vmin); display: flex; justify-content: center; align-items: center;">
            <div id="output" style="border: 2vmin solid rgb(15, 31, 46); width: 40vmin; height: 40vmin; border-radius: 50%; transform: translate(0vmin); background-color: rgb(15, 31, 46); box-sizing: border-box;"></div>
        </div>
        <script>
            const { controller, InputType } = UniversalGameController;
            const output = document.querySelector('#output');
            const instructions = document.querySelector('#instructions');

            const gameLoop = () => {
                const move = controller.move;
                output.style.transform = `translate(${move.x * 25}vmin, ${move.y * 25}vmin)`;

                if (controller.trigger) {
                    output.style.width = '60vmin';
                    output.style.height = '60vmin';
                } else {
                    output.style.width = '30vmin';
                    output.style.height = '30vmin';
                }

                if (controller.type === InputType.KEYBOARD) {
                    instructions.innerText = 'Use WASD to move and space to trigger';
                } else if (controller.type === InputType.TOUCH) {
                    instructions.innerText = 'Use one finger to move and another to trigger';
                } else if (controller.type === InputType.GAMEPAD) {
                    instructions.innerText = 'Use the left stick to move and button 1 to trigger';
                }

                requestAnimationFrame(gameLoop);
            }
            gameLoop();
        </script>
    </body>
</html>

Ideas

  • Configurations for gamepad joystick dead zone and touchscreen virtual joystick size.
  • Provide the current touch coordinates for displaying virtual joysticks.
  • Capturing touch input only on specific DOM elements.
  • Twin-stick.
  • Events for trigger button state change.
  • Mouse support (because WASD has only 8 directions and this can be too limiting in top-down shooting games).
  • Optional joystick smoothing (to make it easier to move only a tiny bit with WASD).
  • More buttons with game-defined graphics for touchscreen version (how to hide them when touch screen is not present?)

Non-goals

  • Anything that displays graphics (e.g. virtual joysticks).
  • Anything that requires user action to enable (e.g. motion sensor).
  • Local multiplayer. Well, maybe. Multiplayer is fun, but this gets a bit complicated to handle in a generic way. The main point of this library is to provide an opinionated mapping between different input types, and there more trade-offs with 2-player control mapping possibilities.
  • Exposing all features of each input method. If you need more, just use the vanilla APIs – they are not that complicated.
  • XR / 3D input.

Keywords

FAQs

Last updated on 12 Jul 2023

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc