*_input — Reacting to player input#

Kate supports multiple input sources, such as the Kate gamepad and pointer input. Each of these input sources has a distinct API exposed, and this section describes all of the different input APIs.

State updates#

Input states are updated from the Kate Kernel by sending messages to the cartridge process. They are then synchronised using the Timer API, which ticks at 30 FPS. This means that the best way to read button states is to schedule your updates using the Timer API as well, otherwise APIs like is_just_released() will have no defined meaning.

For example, if you’re using requestAnimationFrame to update your game, then querying the button state might end up reporting that a button was “just pressed” or “just released” multiple frames in a row:

Non-recommended way of interacting with the input APIs.#
function update() {
  if (KateAPI.input.is_just_pressed("menu")) {
    show_menu_screen();
  } else if (KateAPI.input.is_just_pressed("o")) {
    next_dialogue();
  }

  requestAnimationFrame(update);
}

// Don't do this, input states will not have been properly updated when
// your function is called!
requestAnimationFrame(update);

Instead, use the Timer API to schedule your updates:

KateAPI.timer.on_tick.listen(time => {
  if (KateAPI.input.is_just_pressed("menu")) {
    show_menu_screen();
  } else if (KateAPI.input.is_just_pressed("o")) {
    next_dialogue();
  }
});

Alternatively, instead of pulling input states in your update function, you can have them pushed to your cartridge code by listening to input state change events. This method requires no synchronisation with the Kate timer since all changes are propagated as discrete events, but requires you to write your code in an event-driven manner.

For example:

KateAPI.input.on_key_pressed.listen(({ key }) => {
  if (key === "menu") {
    show_menu_screen();
  } else if (key === "o") {
    next_dialogue();
  }
});

Kate buttons (input)#

The Kate buttons API (input) allows a cartridge to react to buttons pressed in the standard Kate gamepad. This gamepad is made out of:

  • A four-directions D-pad (D-Pad);

  • Four face buttons: Ok button (a.k.a. O) (Ok), Cancel button (a.k.a. X) (Cancel), Sparkle button (Sparkle), and Menu button (Menu);

  • Two shoulder buttons: Left shoulder button and Right shoulder button; and

  • Two special buttons: Capture button (Capture button) and Berry button (Berry button).

Although your cartridge reacts to these Kate buttons, a player may be interacting with it through other means. E.g.: players running a Kate emulator on a PC might be interacting with your cartridge through a keyboard. Whereas players running a Kate emulator on a phone might be interacting with your cartridge through virtual buttons using their touch screen. In all cases the Kate emulator translates these distinct input sources into Kate button presses, so you don’t need to be aware of them.

Pause state#

When the player brings up the context menu, Kate considers the game paused and will not forward any input to the cartridge during this period. That lasts until the cartridge goes back to running in the foreground.

This state is readable from the input API and can be used by the cartridge to avoid updating other game entities while the player is not actively interacting with it.

property KateAPI.input.is_paused: boolean#

Returns whether the cartridge is in a “paused” state, where the Kate Kernel will not be forwarding input to it because it’s not the application currently in the foreground.

Example

function update(lag) {
  if (!KateAPI.input.is_paused) {
    player.update(lag);
    for (const enemy of enemies) {
      enemy.update(lag);
    }
  }
}

Button identifiers#

class KateAPI.input.InputKey#

Each button in the Kate gamepad is identified by a unique string. These are referred to as InputKey below:

Button

Identifier

Ok button (a.k.a. O)

o

Cancel button (a.k.a. X)

x

Sparkle button

sparkle

Menu button

menu

D-Pad

up, right, down, left

Left shoulder button

ltrigger

Right shoulder button

rtrigger

Capture button

capture

Berry button

berry

Warning

ltrigger and rtrigger will be renamed to l and r in the next version and the current identifiers will be deprecated.

Berry button and Capture button are special in that Kate distinguishes between a short and long press. This also means that state changes for these buttons is delayed until the player releases the button, so Kate can decide whether to report that as a “short” or “long” press.

Other buttons do not have a concept of “long press”, but may be considered repeat presses if the player presses the button and doesn’t release it for a long period of time.

class KateAPI.input.KeyPressedEvent#

Represents a key being pressed.

property key: InputKey#

The key that was pressed.

property is_repeat: boolean#

True if the key was pressed in a previous frame, but remains pressed in this one.

property is_long_press: boolean#

True if the key is special (berry or capture) and the player has held it for longer than the long-press threshold.

Events#

The input API provides two events for discrete changes to the button states. These are forwarded directly from the Kate Kernel and propagated to any listener in the cartridge.

property KateAPI.input.on_key_pressed: EventStream[KeyPressedEvent]#

Emitted whenever the player presses a button, with some delay for special keys. Repeat presses may trigger this event multiple times for the same key, and in that case is_repeat will be set to true.

Querying button states#

Button states are updated at 30 FPS. If you’re looking to query them in your game you’ll need to make sure you’re using the Timer API to keep your update loop synchronised with Kate’s button state updates, otherwise the functions will have no defined meaning and you might find that the controls for your game fail randomly.

KateAPI.input.is_pressed(key: InputKey) boolean#
Parameters:

key – The button (one of the Button identifiers) to test.

Tests whether the button is pressed at this point in time. This function does not require strong synchronisation, since the main thread cannot have concurrent modifications to the button states.

KateAPI.input.frames_pressed(key: InputKey) number#
Parameters:

key – The button (one of the Button identifiers) to query.

Returns the number of frames that the button has been held down, fully pressed. This is according to the Timer API, so you must synchronise your queries using the same API for the return value to make sense.

KateAPI.input.is_just_pressed(key: InputKey) boolean#
Parameters:

key – The button (one of the Button identifiers) to query.

Returns whether the button was pressed this exact frame, according to the KateAPI.timer. You must synchronise your queries with the Timer API.

KateAPI.input.is_just_released(key: InputKey) boolean#
Parameters:

key – The button (one of the Button identifiers) to query.

Returns whether the button was released this exact frame, according to the KateAPI.timer. You must synchronise your queries with the Timer API.

Pointer input (pointer_input)#

The Pointer API (pointer_input) allows a cartridge to react to pointer events that happen when the cartridge is the foreground application (i.e.: when the player is actively interacting with it).

A pointer event can come from many different input devices, the most common one being a mouse. But touch input and pen/stylus devices also generate pointer events. The design takes after the DOM pointer events. That is, pointing devices are anything that can target some coordinate on the screen, and the pointer API provides ways to react to this pointer moving or touching/parting from the screen.

Note

Currently the pointer API does not support pen pressure, tilt, and other more complex properties, but they’re planned for a future revision.

The Kate pointer API only supports one active pointer. That is, there is only one coordinate in the screen that the pointing device can be pointing at at any given time.

Pointer location#

Pointing devices allow the player to target specific coordinates of the screen, which they do so by moving a “pointer” around. For example, a player using a mouse can move the mouse around to change where the pointer in the screen points at. A player using a trackpad can do the same by sliding their finger around the pad. All of these movements generate discrete pointer movement events and update the current location of the pointer.

For example, a cartridge that wishes to change how a button on the screen looks when the player moves the pointer on top of it could do so as follows:

const button = {
  color: "#ccc",
  left: 100,
  top: 100,
  right: 200,
  bottom: 200
};

KateAPI.timer.on_tick.listen(time => {
  const pointer = KateAPI.pointer.location;
  if (
    pointer.x >= button.left && pointer.x <= button.right &&
    pointer.y >= button.top && pointer.y <= button.bottom
  ) {
    button.color = "#039";
  } else {
    button.color = "#ccc";
  }

  const canvas = document.querySelector("#canvas");
  const ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, 300, 300);
  ctx.fillStyle = button.color;
  ctx.fillRect(button.left, button.top, button.right - button.left, button.bottom - button.top);
});

Types#

class KateAPI.pointer_input.PointerLocation#

Represents the coordinates of the pointer on the cartridge screen.

property x: number#

The horizontal position of the pointer on the cartridge screen, in pixels.

property y: number#

The vertical position of the pointer on the cartridge screen, in pixels.

Events#

Discrete events are emitted whenever a pointer changes. While the events are still throttled at 30 FPS, your cartridge can build its own synchronisation when handling them.

property KateAPI.pointer_input.on_moved: EventStream[PointerLocation]#

Emitted whenever the position of the pointer on the screen changes.

Querying state#

The state is updated at 30 FPS, so you’ll need to use the KateAPI.timer API to synchronise your updates with the input state updates to be able to get something sensible out of the data.

property KateAPI.pointer_input.x: number#

The horizontal position of the pointer in the cartridge screen, in pixels.

property KateAPI.pointer_input.y: number#

The vertical position of the pointer in the cartridge screen, in pixels.

property KateAPI.pointer_input.location: PointerLocation#

The horizontal and vertical position of the pointer in the cartridge screen, in pixels.

Pointer buttons#

A pointing device can have one or more buttons, whith the player can then press. When they do so Kate will provide events on which button was pressed along with the coordinate where the pointer was at the time.

For example, when using a mouse the player can move the pointer around the screen and then press the primary mouse button (say the left button). The game can then interpret this as the player wishing to paint that coordinate on the screen. It may react similarly if the player touches the screen at that point, or presses the stylus against a digitizer.

But players can press a secondary mouse button (say the right button) as well. In this case a game may decide to interpret this action by showing a context menu instead of painting that location.

const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");

KateAPI.pointer_input.on_clicked.listen(event => {
  ctx.fillRect(event.location.x, event.location.y, 1, 1);
})

KateAPI.pointer_input.on_alternate.listen(event => {
  show_context_menu();
});

Types#

class KateAPI.pointer_input.PointerButton#

A string representing the button of a pointer device. Can be either primary or alternate.

class KateAPI.pointer_input.PointerClick#

Represents the click of a button at a particular pointer coordinate.

property location: PointerLocation#

The coordinates where the pointer was at the time the click happened.

property button: PointerButton#

The button that was pressed. primary is for the primary button on a mouse or a pen making contact with the digitizer. alternate is the code for every other button, as Kate does not distinguishes between different alternate buttons.

Events#

Discrete events are emitted whenever the state of a button in the pointing device changes. These are throttled at 30 FPS, but your cartridge can build your own synchronisation when listening to them.

property KateAPI.pointer_input.on_clicked: EventStream[PointerClick]#

Emitted whenever a pointer button is pressed.

property KateAPI.pointer_input.on_down: EventStream[PointerClick]#

Emitted whenever one of the pointer buttons is pressed. You can use the PointerClick.button property to distinguish which button was pressed.

property KateAPI.pointer_input.on_up: EventStream[PointerClick]#

Emitted whenever one of the pointer buttons is released. You can use the PointerClick.button property to distinguish which button was released.

Querying state#

Button states update at 30 FPS. In order to query them you’ll need to synchronise your calls with the KateAPI.timer API.

KateAPI.pointer_input.frames_pressed(button: PointerButton) number#
Parameters:

button – The identifier of the button to query.

Returns the number of frames the button has been pressed for.

KateAPI.pointer_input.is_pressed(button: PointerButton) boolean#
Parameters:

button – The identifier of the button to query.

Returns true if the button is pressed at all at the time this is called. This call does not have to be synchronised with the Timer API.

KateAPI.pointer_input.is_just_pressed(button: PointerButton) boolean#
Parameters:

button – The identifier of the button to query.

Returns true if the button was pressed during this frame. This only makes sense if your update function is synchronised with the Timer API.

KateAPI.pointer_input.is_just_released(button: PointerButton) boolean#
Parameters:

button – The identifier of the button to query.

Returns true if the button was released during this frame. This only makes sense if your update function is synchronised with the Timer API.