Code Monkey home page Code Monkey logo

game-inputs's Introduction

game-inputs

A simple library for abstracting key/mouse input for games.

Does stuff like:

  • Virtual key bindings (i.e. map one or more physical keys to a single action)
  • Emits down/up events for each binding (not each key)
  • Handles annoying edge cases, like overlapping events from two keys bound to the same action, or the browser losing focus while a key is pressed, etc.
  • Exposes objects with the current state of each binding, the number of press/release events since the last tick, etc.
  • Also tracks mouse/pointer events and scroll/wheel inputs

Canonical names for physical keys are as specified by KeyboardEvent.code. To check key codes, try the live demo.

Sample usage:

import { GameInputs } from 'game-inputs'

// instantiate
var domElement = document.querySelector('...')
var inputs = new GameInputs(domElement, {
  preventDefaults: true, 
  allowContextMenu: false,
})

// bind an arbitrary event name to one or more physical key codes
inputs.bind( 'move-fwd',  'KeyW' )
inputs.bind( 'move-left', 'KeyA', 'ArrowLeft' )

// listen to that event name for press/release events
inputs.down.on( 'move-fwd', (ev) => { startMovingFwd() } )
inputs.up.on( 'move-fwd', (ev) => { stopMovingFwd() } )

// mouse/pointer buttons are bindable as `Mouse1`, `Mouse2`, ...
inputs.bind( 'shoot', 'Mouse1' )
inputs.bind( 'RMB', 'Mouse3' )

// you can also query various input states in the game loop
function myGameLoop() {
  // current boolean state of a key or mouse button
  var leftCurrentlyPressed = inputs.state['move-left']
  var shootButtonPressed = inputs.state['shoot']

  // pointer movement and scroll/wheel data
  var mouseMovedBy = [inputs.pointerState.dx, inputs.pointerState.dy]
  var scrolledBy = inputs.pointerState.scrolly

  // accumulated number of presses/releases since the last tick
  var fwdPresses = inputs.pressCount['move-fwd']
  var fwdReleases = inputs.releaseCount['move-fwd']

  // calling tick() zeroes out cumulative mouse/scroll/press/release values
  inputs.tick()
}

// you can optionally filter events before they occur - e.g. if you want
// keyboard events not to fire if control keys are pressed
inputs.filterEvents = (ev, bindingName) => {
    if (/^Key/.test(ev.code) && ev.ctrlKey) return false
    return true
}

Here's the interactive demo.

Installation

npm install game-inputs

API

The various methods and properties are documented via doc comments, so in a modern editor you should hopefully see them as tooltips.

Otherwise, please see the source ;)

Notes:

  • When you specify a domElement, this module will only track pointer inputs (movement, clicks, and scrolls) inside that element. However keyboard inputs will be tracked globally at the document level.
  • If you don't specify a DOM element, document will be used.
  • For several reasons, this module doesn't call preventDefault or stopPropagation on mouse or scroll events, even if those properties are set. If you want to prevent parts of your page from scrolling or panning, it's more performant to do so via CSS.

Known issues:

  • On Mac keyup events never fire while the Command key is pressed (see here), so if the user presses cmd+A it's impossible to detect whether the A key gets released. There's no great way to work around this - this library errs on the side of avoiding phantom key inputs by emulating an up for such key chords when the Command key is released.


History

  • 0.8.0 Works around mac-only command key bug
  • 0.7.0 Adds filterEvents()
  • 0.6.0 Modernization pass - adopts real physical key codes, Pointer events (still fallback to mouse), etc. Also adds proper docs/types.
    Breaking changes:
    • now an ES module exporting a named class, not a factory function
    • Key binding names now use KeyboardEvent.code strings (e.g. KeyA, Space)
    • Bindings for mouse buttons are now Mouse1, Mouse2..
    • Mouse/scroll values (dx,dy,scrollx,scrolly) moved from inputs.state to inputs.pointerState
  • 0.5.0 Minor features and dependency updates
  • 0.3.0 Stable release

By

Made with ๐Ÿบ by Andy Hall.

License is ISC.

Originally modeled after game-shell, but probably doesn't resemble it much anymore.

game-inputs's People

Contributors

fenomas avatar mcarth avatar nornagon avatar thetoto avatar

Stargazers

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

Watchers

 avatar  avatar

game-inputs's Issues

Joystick support

Ideally this library should know how to consume joystick events and send them to a binding. Have not looked into it carefully yet, though.

Plans for full touch support?

I'm having some performance issues with my touch implementation - before I put too much time into it, I'm wondering if you have plans to implement full touch support here and in noa in the short term and/or long term?

State object for cumulative presses per frame

Separate to the state object, there should be an object that counts press events and is cleared each frame by tick. This will let games process all inputs discretely in their tick function if they want to.

Add mouse scroll events

This should do something on scroll events. Probably it should match mouse clicks - issue a (misnamed?) down event, and update the (NYI) object that tracks events since the last frame (see #1).

Mouse up event never firing when pointer lock lost

Hi, I've run into an issue where if pointer lock is removed while a mouse button is being held down, the up event never fires (due to it being bound to the canvas, and not the document). For my game, this is an issue when the player dies, a menu opens, and they could have been clicking while they died. This leads to the mouse down event being essentially ignored as the state is already that it is down.

I see two ways of fixing this:

  1. On pointer lock lost, set state to false. (I've gone for this as it was easier, modifying onLockChange like so:)
var numMouseEvts = 3
function onLockChange(inputs, ev) {
    var locked = document.pointerLockElement
        || document.mozPointerLockElement
        || null
    if (locked) inputs._ignoreMousemoveOnce = true
    
    if (!locked) {
        for (var i = 1; i < numMouseEvts+1; ++i) {
            var vkeycode = '<mouse ' + i + '>'
            var keycode = -i
            handleKeyEvent(keycode, vkeycode, false, inputs, {preventDefault: () => {}, stopPropagation: () => {}})
        }        
    }
}
  1. add event listener to the document, once pointer lock is lost, only listen to the first up event for something that is currently down. Seems like a bit more effort, but the better user experience.

I'm happy to submit a PR with what I've done in 1 if useful, let me know what you think.

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.