UNPKG

evidently-input

Version:

TypeScript powered for easily handling input in your games.

95 lines (94 loc) 4.51 kB
/** * Handles the keyboard events and provides an API for interacting with it easily. The simplest way to use it is: * * 1. Create a new instance of `KeyboardInput`. * 2. Call `registerListeners()` passing the `document`. * 3. Call `update` **at the end** of every update frame of your game. * 4. Use the functions of this library in your code. * * ### How does it work? * * You need to call the `update()` method at the **end** of every frame to properly transition internal state. * The workflow for this class is as follows: * 1. Browser receives events from the user and fires the corresponding events. * 2. `KeyboardInput` receives those events and updates its internal state. * 3. Update loop for your game runs and you can use the methods in this class to interact. * 4. At the end of the your game's update loop `update()` is called on this class. (or at any point past when you know you'll interact with this class) * 5. Repeat * * ### Understanding key states * * There are three states recognized by this class for a key: down, pressed and released: * * * Use `pressed` if you want to know if a key was pressed at least once this frame. * * Use `released` if you want to knof iw a key was releast at least once this frame. * * Use `down` if you want to know if a key was either pressed this frame or pressed in any previous frame and not released so far. * * * You may notice that in a situation where during the course of a single frame a key is both pressed and released, all three states * will report true. That's an intentional design decision to avoid a very uncommon but still possible bug. Imagine this code: * * ``` * if (keyboardInput.isKeyDown("a")) { * this.move({x: -1}); * } * ``` * * If for some reason your game runs slow (maybe it naturally has low FPS or it's lagging at the moment), if you pressed and released the `a` key * during the span of a single frame as a player you'd still expect the move to trigger - sure, you released the key but you also pressed it. The * code can't use `isKeyPressed` instead, because you want the player to keep moving as long as the key is down. You could work around this by * expanding the condition to `i.isKeyDown || i.isKeyPressed`, but the issues are: * * 1. You probably didn't think about this bug in the first place. Which is fine, it's extremely unlikely to ever be an issue for the vast majority * of games. * 2. The expanded condition is less readable. * 3. The change on its own doesn't break anything, so you lose nothing by having it baked in the system. */ export declare class KeyboardInput { private _keysDown; private _keysPressed; private _keysReleased; private _isCtrlDown; private _isShiftDown; private _isAltDown; private _wasCtrlDownThisFrame; private _wasShiftDownThisFrame; private _wasAltDownThisFrame; private _lastKeyPressed; get isCtrlDown(): boolean; get isShiftDown(): boolean; get isAltDown(): boolean; get isAnyKeyDown(): boolean; get isAnyKeyPressed(): boolean; get isAnyKeyReleased(): boolean; get lastKeyPressed(): string; isKeyDown: (key: string) => boolean; isKeyPressed: (key: string) => boolean; isKeyReleased: (key: string) => boolean; constructor(); /** * Updates the internal state, should be called at the end of each frame. */ update: () => void; /** * Resets the internal state of this class to what it is during creation (nothing pressed, released or held down) */ flush: () => void; /** * Registers the `keydown` and `keyup` listeners on the passed element so that the class * can handle the input. * * @param {GlobalEventHandlers} element To avoid issues with focus it's best to pass `document` here */ registerListeners(element: GlobalEventHandlers): void; /** * Handles a keyboard event updating the internal status. This will be called automatically if you register the listeners * via `registerListeners`. If you have listeners being registered somewhere else entirely and would like to keep it * that way, you can manually call this method passing the KeyboardEvent. * * @warning This method will call `preventDefault` on the event passed. * * @param {KeyboardEvent} event */ handleEvent: (event: KeyboardEvent) => void; }