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

guki-input-controller

v0.8.8

Published

This is a lightweight JavaScript module that provides a simple input controller class for loop-based game development. It supports keyboard, mouse, and gamepad.

Downloads

6

Readme

guki-input-controller

This is a lightweight JavaScript module that provides a simple input controller class for loop-based game development. It supports keyboard, mouse, and gamepad.

current version: 0.8.8

Overview

Methods

init( viewport = "default" )

This function sets up the controller. It has to be called once before a game loop. The viewport argument chooses the DOM element for mouse coordinates. The default viewport makes them screen-relative.

update()

This function has to be called in the game loop.

Properties

lastActiveDevice

A string - keyboard, mouse or gamepad.

keyboard.pressed

An array of strings that contains the keyboard buttons currently pressed.

keyboard.justPressed

An array of strings that contains the keyboard buttons that have just been pressed in the current iteration.

mouse.pressed

An array of integers that represent the mouse buttons currently pressed.

mouse.justPressed

An array of integers that represent the mouse buttons that have just been pressed in the current iteration.

mouse.x

A number that represents the x-coordinate of the mouse cursor on the screen or on a viewport, which is a specific DOM element that shows part of the document.

mouse.y:

Same as mouse.x but for y-coordinate.

gamepad.pressed

An array of strings that contains the gamepad buttons currently pressed.

gamepad.justPressed

An array of strings that contains the gamepad buttons that have just been pressed in the current iteration.

gamepad.buttonMap

An array of strings that contains the names of the gamepad buttons based on the Xbox button map. It can be modified to support different gamepads.

gamepad.axes

An array of four numbers between -1 and 1 that represent the x and y axes of the left and right sticks of the gamepad.

gamepad.connected

A boolean that indicates whether a gamepad is connected or not.

gamepad.justConnected

A boolean that indicates whether a gamepad has just been connected in the current iteration or not.

gamepad.justDisconnected

A boolean that indicates whether a gamepad has just been disconnected in the current iteration or not.

Installation

npm install guki-input-controller

Usage

import GukiInputController from "guki-input-controller"

const gic = new GukiInputController()

gic.init()

function gameLoop() {
  gic.update()

  if (gic.keyboard.pressed.includes("A")) {
    console.log("Move forward")
  }
  if (gic.keyboard.justPressed.includes("B")) {
    console.log("Switch weapons")
  }
}

Methods

init( viewport = "default" )

This function has to be called once before a game loop is started. The viewport argument specifies the DOM element for mouse x and y coordinates (a code example with them can be found further down in this document). The default viewport makes the mouse coordinates relative to the screen. Some addEventListener methods are added behind the scenes to update the controller states, so init() has to be called within the global scope with the window object.

const gic = new GukiInputController()

// The window object has to exist in some parent scope
gic.init()

function gameLoop() {
  gic.update()

  // check controller states
}

update()

This function has to be called in the game loop before the controller states are checked, as shown in the previous example.

Properties

lastActiveDevice

Could be keyboard, mouse or gamepad.

lastActiveDevice = "keyboard"

keyboard.pressed

keyboard.justPressed

While pressed is used for held-down buttons, justPressed for one-time taps. Let's say we pressed two buttons. On first iteration we would have this controller state :

keyboard.pressed = ["A", "B"]
keyboard.justPressed = ["A", "B"]

We can check it to make some actions:

if (gic.keyboard.pressed.includes("A")) {
  console.log("Move forward")
  // true, will work
}
if (gic.keyboard.justPressed.includes("B")) {
  console.log("Switch weapons")
  // true, will work
}

Even one-tap presses are long enough to take place in a couple of iterations. So on the second iteration both A and B are still pressed. However, switch weapons won`t trigger again, because justPressed is empty.

keyboard.pressed = ["A", "B"]
keyboard.justPressed = []
if (gic.keyboard.pressed.includes("A")) {
  console.log("Move forward")
  // true, will work again
}
if (gic.keyboard.justPressed.includes("B")) {
  console.log("Switch weapons")
  // false, won't work
}

mouse.pressed

mouse.justPressed

Works similarly to the keyboard, but instead of using strings, it uses integers. These integers are constants that are predefined by the browser's JavaScript environment and are related to specific mouse buttons. In this example, both the left and right buttons have been pressed for the first time.

mouse.pressed = [0, 2]
mouse.justPressed = [0, 2]

0 - Left 1 - Middle 2 - Right 3 - Back 4 - Forward

mouse.x

mouse.y

By default, coordinates are screen-relative. However, you can associate them with a specific DOM object, usually the application's viewport. Unlike offsetX and offsetY on a MouseEvent, these coordinates will work regardless of how many other objects are present on top by their z-index. To associate coordinates with the viewport, provide it as an argument to init() method.

mouse.x = 228
mouse.y = 282
import GukiInputController from "guki-input-controller"

const gic = new GukiInputController()

// Assuming you have a DOM element with the "viewport" id
const viewport = getElementById("viewport")

gic.init(viewport)

function gameLoop() {
  gic.update()

  console.log(gic.mouse.x + " " + gic.mouse.y)
  // These coordinates are going to be relative to the viewport DOM element
}

gamepad.pressed

gamepad.justPressed

Works just as the keyboard. It uses specific button names based on the Xbox button map.

gamepad.pressed = ["Start", "LB"]
gamepad.justPressed = ["Start", "LB"]

gamepad.buttonMap

You can customize this value to set your own button map. This is possible either before or after the initialization. Here is the default Xbox-based button map:

gic.gamepad.buttonMap = [
  "A",
  "B",
  "X",
  "Y",
  "LB",
  "RB",
  "LT",
  "RT",
  "Start",
  "Menu",
  "LS",
  "RS",
  "Up",
  "Down",
  "Left",
  "Right",
]

gamepad.axes

An array of four floating-point numbers between -1 and 1. The first and second correspond to the x and y axes of the left stick. The third and fourth respectively of the right stick.

[ left stick x , left stick y , right stick x , right stick y ]

gamepad.axes = [0, 1, -0.912, 0.13]
import GukiInputController from "guki-input-controller"

const gic = new GukiInputController()

gic.init()

const speed = 100

function move() {
  // Assuming you have an entity whose x and y properties define its position
  // The entity’s movement is controlled by the left stick
  entity.x += speed * gic.gamepad.axes[0]
  entity.y += speed * gic.gamepad.axes[1]
}

function gameLoop() {
  gic.update()

  move()
}

Please note that the code example above does not normalize the movement in the diagonal direction for simplicity.

gamepad.connected

gamepad.justConnected

gamepad.justDisconnected

Works similarly to the pressed and justPressed, but instead of arrays, it's booleans.

gamepad.connected = true
gamepad.justConnected = true
gamepad.justDisconnected = false
if (gic.gamepad.connected) {
  console.log("Hide cursor")
}
if (gic.gamepad.justConnected) {
  console.log("Show message")
}

License

This project is licensed under the MIT License - see the LICENSE file for details.

© 2023 Ivan F. Sokolov