Skip to content

Timer

Timer schedules work that should happen over game time: repeating effects, one-off delays, and tweens that smoothly change numeric values. Game advances its shared Timer once per frame, so durations use seconds, not milliseconds.

Create a timer once and advance it from your game’s update loop. Game already does this for its services.timer instance; states can use that same timer through this.game.timer.

const timer = new Timer();
function update(dt) {
timer.update(dt);
}
// Schedule work anywhere that can access the timer.
timer.after(0.5, () => {
console.log('Half a second has passed.');
});
flowchart TD
  A[Game loop receives dt in seconds] --> B["Timer.update(dt)"]
  B --> C[Remove tasks marked done\nfrom a previous frame]
  C --> D[Advance every active Task]
  D --> E{Interval reached?}
  E -- yes --> F[Run task action]
  E -- no --> G{Duration reached?}
  F --> G
  G -- yes --> H[Run completion callback\nand mark task done]
  G -- no --> I[Keep task scheduled]
  H --> J[Next update removes it]

Creates an empty scheduler.

timer.update(dt);

Advances every scheduled task by dt seconds. Call it once per frame when using a standalone timer. Game.update(dt) already does this for services.timer; see delta time for the meaning of dt.

const handle = timer.every(interval, action);

Runs action repeatedly. interval is measured in seconds. An interval of 0 runs the action once on every timer update. Returns a timer handle that can stop the task.

// Increment a counter once per second.
const counterHandle = timer.every(1, () => {
counter++;
});
// Stop the clock later.
counterHandle.cancel();
const handle = timer.after(duration, action);

Runs action once after duration seconds and returns a timer handle.

// Hide a notification after a short delay.
timer.after(2, () => {
notification.visible = false;
});

Use a positive duration. A task whose duration has elapsed is marked done after its callback runs and is removed at the beginning of the next update().

timer.cancelAll();

Immediately clears the timer’s task list. Use it when disposing a screen, resetting a scene, or otherwise discarding work that must not continue later. A State can do this from exit() when it owns work that must not outlive that state.

function dispose() {
timer.cancelAll();
}

tween(object, parameters, duration, options)

Section titled “tween(object, parameters, duration, options)”
const handle = timer.tween(object, parameters, duration, options);

Changes one or more numeric properties from their current values to the values in parameters over duration seconds. It runs in the background; code after tween() continues immediately. Returns a timer handle.

options is optional and may contain:

  • easing: an easing function; defaults to Easing.linear. See the Easing reference.
  • callback: a function called after the tween reaches its destination.
import { Easing } from './lib/Easing.js';
const panel = { x: 0, opacity: 0 };
timer.tween(panel, { x: 96, opacity: 1 }, 0.25, {
easing: Easing.easeOutQuad,
callback: () => {
console.log('Panel is visible.');
},
});

The timer records each starting value when the tween is scheduled. On each frame it calculates and assigns the next value; the final frame is clamped to the exact destination.

sequenceDiagram
  participant Code as Application code
  participant Timer
  participant Panel
  Code->>Timer: tween(panel, { x: 96 }, 0.25)
  Note over Code: Continues immediately
  loop Each Timer.update(dt)
    Timer->>Panel: set x to eased value
  end
  Timer->>Panel: set x = 96 (final value)
  Timer-->>Code: run options.callback()

tweenAsync(object, parameters, duration, easing)

Section titled “tweenAsync(object, parameters, duration, easing)”
await timer.tweenAsync(object, parameters, duration, easing);

Starts a tween and returns a Promise that resolves when it finishes. Await it when later code must wait for the animation.

const firstPanel = { x: 0 };
const secondPanel = { x: 320 };
// Start both movements together, then continue when both finish.
await Promise.all([
timer.tweenAsync(firstPanel, { x: 320 }, 0.2),
timer.tweenAsync(secondPanel, { x: 0 }, 0.2),
]);
console.log('Panels have swapped places.');

Awaiting pauses only the surrounding async function. It does not pause rendering, input processing, or Timer.update(dt), which Game continues to call every frame.

await timer.delay(duration);

Returns a Promise that resolves after duration seconds without changing any properties. It is useful for readable async sequences.

async function showNotification() {
notification.visible = true;
await timer.delay(0.15);
notification.highlighted = true;
}

every(), after(), and tween() return a TimerHandle:

const handle = timer.every(1, action);
console.log(handle.isDone); // false
handle.cancel(); // Prevent future scheduled updates.
console.log(handle.isDone); // true

A handle has these members:

Member Description
cancel() Marks this task done without running its completion callback.
isDone true after cancellation or after a duration-based task completes.

A cancelled or completed task is removed when Timer.update() next begins. Keep the handle when you may need to stop one task; use cancelAll() when discarding every task in the timer.