phaserjs/phaser1 file

Time And Timers

Use this skill when using timers and time-based events in Phaser 4. Covers TimerEvent, delayed calls, looping timers, the Clock plugin, and time scaling. Triggers on: timer, delay, delayedCall, TimerEvent, Clock, time event.

Specification
Skill ID
phaserjs/phaser/time-and-timers
Publisher
phaserjs
Repository
phaser
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

phaserjs/phaser/time-and-timersInstalls these files
  • SKILL.md

What this skill tells the agent

Time and Timers

Clock plugin, TimerEvent, delays, loops, Timeline event sequencing, pausing time, time scale, and delta time in Phaser 4.

Key source paths: src/time/Clock.js, src/time/TimerEvent.js, src/time/Timeline.js, src/time/typedefs/, src/time/events/ Related skills: ../scenes/SKILL.md, ../tweens/SKILL.md

Quick Start

// In a Scene's create() method:

// One-shot delayed call (fires once after 1 second)
this.time.delayedCall(1000, () => {
    console.log('One second later');
});

// Repeating timer (fires 5 times, once every 500ms)
this.time.addEvent({
    delay: 500,
    callback: () => { console.log('tick'); },
    repeat: 4   // 4 repeats = 5 total fires
});

// Infinite loop timer
this.time.addEvent({
    delay: 1000,
    callback: this.spawnEnemy,
    callbackScope: this,
    loop: true
});

this.time is the scene's Clock instance (registered as the 'Clock' plugin under the key time). It creates and manages TimerEvent objects that fire callbacks based on game time.

Core Concepts

Clock (this.time)

The Clock is a Scene-level plugin that tracks game time and updates all of its TimerEvents each frame. Key properties:

  • `now` -- current time in ms (equivalent to time passed to the scene update method).
  • `startTime` -- timestamp when the scene started.
  • `timeScale` -- multiplier applied to delta time. Default 1. Values above 1 speed up all timers; below 1 slow them down; 0 freezes time.
  • `paused` -- when true, no TimerEvents are updated.

The Clock listens to PRE_UPDATE (to flush pending additions/removals) and UPDATE (to tick active events). It is automatically shut down and destroyed with the scene.

TimerEvent

A TimerEvent accumulates elapsed time each frame: elapsed += delta * clock.timeScale * event.timeScale. When elapsed >= delay, the callback fires. After all repeats are exhausted the event is removed from the Clock on the next frame.

Key properties set via config: delay, repeat, loop, callback, callbackScope, args, timeScale, startAt, paused.

Timeline (this.add.timeline)

A Timeline is a sequencer for scheduling actions at specific points in time. Unlike the Clock (which manages independent timers), a Timeline runs a linear sequence of events keyed by absolute or relative timestamps.

const timeline = this.add.timeline([
    { at: 0,    run: () => { /* immediate */ } },
    { at: 1000, run: () => { /* at 1s */ } },
    { at: 2500, tween: { targets: sprite, alpha: 0, duration: 500 } }
]);
timeline.play();

Timelines always start paused. You must call play() to start them. They are created via the GameObjectFactory and destroyed automatically when the scene shuts down.

Common Patterns

Delayed Call

// Shorthand -- fires once, no repeat
this.time.delayedCall(2000, () => {
    this.scene.start('GameOver');
});

Repeating Timer with Finite Count

// repeat: 9 means 10 total fires (1 initial + 9 repeats)
const timer = this.time.addEvent({
    delay: 200,
    callback: this.fireBullet,
    callbackScope: this,
    repeat: 9
});

// Check progress
timer.getRepeatCount();       // repeats remaining
timer.getOverallProgress();   // 0..1 across all repeats

Infinite Loop

const spawner = this.time.addEvent({
    delay: 3000,
    callback: this.spawnWave,
    callbackScope: this,
    loop: true
});

// Stop it later
spawner.remove();  // or spawner.paused = true to pause

Setting repeat: -1 is equivalent to loop: true.

First-Fire Shortcut with startAt

// First fire happens quickly (after 100ms), then every 2s
this.time.addEvent({
    delay: 2000,
    callback: this.heartbeat,
    callbackScope: this,
    loop: true,
    startAt: 1900  // pre-fill elapsed so first fire is at 100ms
});

Stopping and Removing Timers

const timer = this.time.addEvent({ delay: 1000, loop: true, callback: fn });

// Option 1: Remove from clock (schedules removal next frame)
timer.remove();            // silently expires
timer.remove(true);        // fires callback one last time, then expires

// Option 2: Remove via Clock
this.time.removeEvent(timer);

// Option 3: Remove all timers
this.time.removeAllEvents();

Pausing and Resuming

// Pause the entire Clock (all timers freeze)
this.time.paused = true;
this.time.paused = false;

// Pause a single timer
timer.paused = true;
timer.paused = false;

Time Scale (Slow Motion / Fast Forward)

// Slow all timers in this scene to half speed
this.time.timeScale = 0.5;

// Speed up a single timer to 2x
timer.timeScale = 2;

// Combined: effective scale = clock.timeScale * event.timeScale
// So 0.5 * 2 = 1x for that specific timer

Reading Timer State

timer.getProgress();              // 0..1 for current iteration
timer.getOverallProgress();       // 0..1 across all repeats
timer.getElapsed();               // ms elapsed this iteration
timer.getElapsedSeconds();        // seconds elapsed this iteration
timer.getRemaining();             // ms until next fire
timer.getRemainingSeconds();      // seconds until next fire
timer.getOverallRemaining();      // ms until final fire
timer.getOverallRemainingSeconds(); // seconds until final fire
timer.getRepeatCount();           // repeats left

Timeline: Sequencing Events

const timeline = this.add.timeline([
    {
        at: 0,
        run: () => { this.title.setAlpha(1); },
        sound: 'intro'
    },
    {
        at: 2000,
        tween: { targets: this.title, y: 100, duration: 1000 },
        sound: { key: 'whoosh', config: { volume: 0.5 } }
    },
    {
        at: 4000,
        set: { alpha: 0 },
        target: this.title,
        event: 'INTRO_DONE'
    }
]);

timeline.on('INTRO_DONE', (target) => { /* custom event */ });
timeline.on('complete', (tl) => { /* all events ran */ });
timeline.play();

Timeline: Relative Timing with from and in

const timeline = this.add.timeline([
    { at: 1000, run: stepOne },         // absolute: 1s from start
    { from: 500, run: stepTwo },        // relative: 500ms after previous (1.5s)
    { from: 1000, run: stepThree }      // relative: 1000ms after previous (2.5s)
]);
  • `at` -- absolute ms from timeline start (default 0).
  • `in` -- offset from current elapsed time (useful when adding events to a running timeline).
  • `from` -- offset from the previous event's start time.

Priority: from overrides in, which overrides at.

Timeline: Conditional Events

const timeline = this.add.timeline([
    {
        at: 5000,
        if: () => this.player.health > 0,
        run: () => { this.showBonusRound(); }
    }
]);

If the if callback returns false, the event is skipped (marked complete but actions are not executed).

Timeline: Looping

const timeline = this.add.timeline([
    { at: 0, run: () => console.log('start') },
    { at: 1000, run: () => console.log('end') }
]);

timeline.repeat().play();      // infinite loop
timeline.repeat(3).play();     // loop 3 additional times (4 total runs)
timeline.repeat(false).play(); // no looping

The loop callback on a TimelineEventConfig fires on repeat iterations (not the first run).

Timeline: Pause, Resume, Stop, Reset

timeline.pause();      // freezes elapsed counter and pauses spawned tweens
timeline.resume();     // resumes elapsed counter and unpauses spawned tweens
timeline.stop();       // sets paused=true, complete=true
timeline.reset();      // elapsed=0, all events marked incomplete, starts playing
timeline.isPlaying();  // true if not paused and not complete
timeline.getProgress(); // 0..1 based on events completed / total events

Timeline: Time Scale

timeline.timeScale = 2;   // double speed
timeline.timeScale = 0.5; // half speed

Use this skill in a project

Open any RiverX project, search the Skills panel for phaserjs/phaser/time-and-timers, and install it in one click.

Use this skill