Skip to content

Input Handling

Estella provides input handling through the Input resource. The InputPlugin is registered by the engine automatically, binding DOM keyboard, mouse, touch, and scroll events.

Using Input in Systems

Access input state through the Res(Input) system parameter:

import { defineSystem, addSystem, Res, Input, Query, Mut, Transform } from 'esengine';
addSystem(defineSystem(
[Res(Input), Query(Mut(Transform))],
(input, query) => {
for (const [entity, transform] of query) {
if (input.isKeyDown('KeyW')) {
transform.position.y -= 5;
}
if (input.isKeyDown('KeyS')) {
transform.position.y += 5;
}
if (input.isKeyDown('KeyA')) {
transform.position.x -= 5;
}
if (input.isKeyDown('KeyD')) {
transform.position.x += 5;
}
}
}
));

Keyboard Input

Key State

// Currently held down (true every frame while held)
if (input.isKeyDown('Space')) {
charge();
}
// Just pressed this frame (true for one frame only)
if (input.isKeyPressed('Space')) {
jump();
}
// Just released this frame (true for one frame only)
if (input.isKeyReleased('Space')) {
releaseCharge();
}

Key Codes

Use standard DOM key codes:

// Letters
'KeyA', 'KeyB', ... 'KeyZ'
// Numbers
'Digit0', 'Digit1', ... 'Digit9'
// Special keys
'Space', 'Enter', 'Escape', 'Tab'
'ShiftLeft', 'ShiftRight', 'ControlLeft', 'ControlRight'
// Arrow keys
'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'
// Function keys
'F1', 'F2', ... 'F12'

Mouse Input

const mousePos = input.getMousePosition();
console.log(`Mouse at: ${mousePos.x}, ${mousePos.y}`);
if (input.isMouseButtonDown(0)) { // Left button
// handle click
}
if (input.isMouseButtonDown(2)) { // Right button
// handle right click
}
// Just pressed / released this frame
if (input.isMouseButtonPressed(0)) {
onClickStart();
}
if (input.isMouseButtonReleased(0)) {
onClickEnd();
}

Scroll Input

const scroll = input.getScrollDelta();
if (scroll.y !== 0) {
zoomCamera(scroll.y);
}

Touch Input

Touch input is unified with mouse input for cross-platform support:

if (input.isMouseButtonDown(0)) {
const pos = input.getMousePosition();
handleTap(pos.x, pos.y);
}

Example: Player Movement

Define Player and MoveSpeed components, attach them to an entity in the scene editor, then write a movement system:

import {
defineSystem, defineComponent, defineTag, addSystem,
Res, Input, Time, Query, Mut, Transform
} from 'esengine';
const Player = defineTag('Player');
const MoveSpeed = defineComponent('MoveSpeed', { value: 200 });
addSystem(defineSystem(
[Res(Input), Res(Time), Query(Mut(Transform), MoveSpeed, Player)],
(input, time, query) => {
for (const [entity, transform, speed] of query) {
const velocity = { x: 0, y: 0 };
if (input.isKeyDown('KeyW') || input.isKeyDown('ArrowUp')) {
velocity.y = -1;
}
if (input.isKeyDown('KeyS') || input.isKeyDown('ArrowDown')) {
velocity.y = 1;
}
if (input.isKeyDown('KeyA') || input.isKeyDown('ArrowLeft')) {
velocity.x = -1;
}
if (input.isKeyDown('KeyD') || input.isKeyDown('ArrowRight')) {
velocity.x = 1;
}
const len = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y);
if (len > 0) {
velocity.x /= len;
velocity.y /= len;
}
transform.position.x += velocity.x * speed.value * time.delta;
transform.position.y += velocity.y * speed.value * time.delta;
}
}
));

Next Steps

  • UI Interaction — UI interaction events (click, hover, press)
  • Physics — physics-driven movement and collision
  • Systems — defining and scheduling systems