К основному содержанию
скилл CX Codex

pixijs-ticker — скилл для Claude Code: логика кадра в PixiJS v8

Скилл объясняет, как устроен цикл рендера PixiJS v8: колбэки тикера, единицы времени, приоритеты и ограничение FPS.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add pixijs/pixijs-skills --skill pixijs-ticker -a claude-code
Открыть на GitHub

Что делает pixijs-ticker

Скилл подключается, когда вы пишете логику на каждый кадр или управляете циклом рендера PixiJS v8. Он разбирает Ticker.add, addOnce и remove, разницу между deltaTime, deltaMS и elapsedMS, порядок вызовов через UPDATE_PRIORITY, ограничения maxFPS и minFPS, масштабирование скорости, выбор между Ticker.shared и собственным экземпляром, хук onRender у объекта сцены и ручной рендер.

Главная ловушка, о которой стоит знать заранее: deltaTime — не миллисекунды. Это deltaMS * Ticker.targetFPMS, где targetFPMS равен 0.06, поэтому при 60 fps получается 1.0, а при 30 fps — уже 2.0. Кто принимает его за время в миллисекундах, тот получает вдвое быструю анимацию на слабом устройстве. Для расчётов в пикселях в секунду берите deltaMS, а elapsedMS оставьте для профилирования: он не масштабируется скоростью и не ограничивается minFPS.

Приоритеты задают порядок вызовов: INTERACTION (50), HIGH (25), NORMAL (0), LOW (-25), UTILITY (-50). Сам app.render() зарегистрирован на LOW через TickerPlugin, так что физика на HIGH успевает до отрисовки. Если передаёте метод класса, вторым аргументом идёт контекст, и в remove нужно повторить и функцию, и контекст — иначе колбэк останется висеть. Ticker.shared и Ticker.system защищены от уничтожения, а new Ticker() создаётся с autoStart = false, и жизненным цикл ведёте вы.

Какие задачи решает

  • добавить логику, которая выполняется каждый кадр
  • выбрать между deltaTime, deltaMS и elapsedMS для анимации
  • задать порядок вызовов физики и отрисовки через UPDATE_PRIORITY
  • ограничить частоту кадров на слабом устройстве
  • привязать обновление к конкретному объекту сцены через onRender

Примеры запросов агенту

  • Добавь вращение спрайта через app.ticker.add с deltaTime, чтобы скорость не зависела от частоты кадров
  • Поставь обновление физики на UPDATE_PRIORITY.HIGH, чтобы оно шло до app.render()
  • Ограничь app.ticker.maxFPS значением 30 и объясни, как это повлияет на deltaMS

Как установить pixijs-ticker

1Через Skills CLI (Vercel)

npx skills add pixijs/pixijs-skills --skill pixijs-ticker -a claude-code

2Вручную: положить файлы

~/.claude/skills/pixijs-ticker/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/pixijs-ticker/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора25

pixijs-events Скилл для работы с указателем, мышью, тачем и колесом в PixiJS v8: режимы eventMode, типы FederatedEvent, всплытие и перехват, hitArea, курсоры, drag через globalpointermove. CX Codex +1 5 900установок pixijs-assets Скилл учит агента загружать ассеты в PixiJS v8 через синглтон Assets. Помогает настроить бандлы, шрифты, спрайтшиты и парсеры для ссылок без расширений. CX Codex +1 5 900установок pixijs-scene-particle-container Инструктирует агента по работе с ParticleContainer в PixiJS v8. Помогает рендерить десятки тысяч легковесных спрайтов за один draw call. CX Codex +1 5 800установок pixijs-filters Помогает настраивать визуальные эффекты PixiJS v8 через систему фильтров. Пригодится для размытия, цветокоррекции и пользовательских шейдеров. CX Codex +1 5 800установок pixijs-scene-text Скилл учит нейросеть работать с текстом в PixiJS v8. Он помогает выбрать подходящий класс рендеринга и не тратить ресурсы на перерисовку канваса каждый кадр. CX Codex +1 5 800установок pixijs-scene-core-concepts Объясняет, как устроено дерево сцены PixiJS v8: контейнеры, листья, трансформы и порядок отрисовки. Пригодится, когда агент пишет код на PixiJS. CX Codex +1 5 900установок pixijs-math Скилл для работы с координатами, матрицами, фигурами и проверкой попаданий в PixiJS v8. Пригодится, когда нужно перевести точку между системами координат или собрать хит-зону. CX Codex +1 5 900установок pixijs-scene-mesh Помогает настраивать кастомную 2D-геометрию в PixiJS v8 через Mesh, MeshPlane, MeshRope и PerspectiveMesh. Пригодится при анимации вершин, деформации текстур и рисовании путей. CX Codex +1 5 700установок

Похожие

pixijs-rendering gamedev-skills Скилл для сборки слоя рендера на PixiJS v8: асинхронный Application, загрузка текстур, сцена на Container, тикер и события указателя. CX Codex +1 5 400установок pixijs-2d freshtechbro Скилл обучает агента создавать 2D-графику на PixiJS с WebGL и WebGPU: анимировать спрайты, выводить частицы и рисовать векторные фигуры на холсте. CX Codex +1 2 500установок remotion-3d-ticker vibe-motion Создаёт зацикленную трёхмерную вертикальную прокрутку для видео в Remotion. Помогает собирать многоколоночные фотостены и титры с параллаксом. CX Codex +1 852установок threejs-animation CloudAI-X Скилл для работы с keyframe-анимацией, костями и морф-целями в Three.js. Помогает воспроизводить glTF-анимации, управлять костями скелета, миксировать и кроссфейдить клипы на WebGL и WebGPU. CX Codex +1 20 400установок orbit-card heygen-com Скилл для встраивания готового 10-секундного 3D-блока HyperFrames: карточка фичи облетает сферу из точек по траектории камеры из Blender. CX Codex +1 10 000установок threejs-gltf-loading gamedev-skills Загружает glTF и GLB в three.js и проигрывает запечённые клипы через AnimationMixer, включая сжатые DRACO, Meshopt и KTX2. Пригодится, когда модель вроде загрузилась, а на экране пусто. CX Codex +1 5 600установок

Рядом в теме «Геймдев и 3D: Unity, Unreal, Godot, Blender»

Всё по теме «Геймдев и 3D: Unity, Unreal, Godot, Blender» →

Вопросы о pixijs-ticker

Как установить pixijs-ticker в Claude?

Выполните npx skills add pixijs/pixijs-skills --skill pixijs-ticker -a claude-code. Скилл окажется в ~/.claude/skills/pixijs-ticker/SKILL.md.

Что делает скилл pixijs-ticker?

Описывает цикл рендера PixiJS v8: колбэки тикера, единицы времени, приоритеты, ограничение FPS и ручной рендер. Помогает не перепутать deltaTime с миллисекундами.

Чем Ticker.shared отличается от нового экземпляра Ticker?

Ticker.shared — синглтон с autoStart = true, защищённый от destroy(). new Ticker() создаётся с autoStart = false, и останавливать, уничтожать его нужно самому.

Исходный текст

SKILL.md · MIT
---
name: pixijs-ticker
description: "Use this skill when running per-frame logic or controlling the PixiJS v8 render loop. Covers Ticker.add/addOnce/remove, deltaTime vs deltaMS vs elapsedMS, UPDATE_PRIORITY ordering, maxFPS/minFPS capping, speed scaling, Ticker.shared vs new instances, per-object onRender hook, manual rendering. Triggers on: Ticker, UPDATE_PRIORITY, deltaTime, deltaMS, elapsedMS, onRender, app.ticker, maxFPS, minFPS, Ticker.shared."
license: MIT
---

`app.ticker` runs registered callbacks every frame and drives `app.render()` at `UPDATE_PRIORITY.LOW`. Each callback receives the Ticker instance; read `deltaTime` as a frame-rate-independent multiplier (≈1.0 at 60fps) or `deltaMS` for real-time calculations.

## Quick Start

```ts
app.ticker.add((ticker) => {
  sprite.rotation += 0.01 * ticker.deltaTime;
  sprite.x += (200 / 1000) * ticker.deltaMS;
});

app.ticker.add(
  (ticker) => {
    updatePhysics(ticker.deltaMS);
  },
  undefined,
  UPDATE_PRIORITY.HIGH,
);

app.ticker.maxFPS = 30;
app.ticker.speed = 0.5;

sprite.onRender = () => {
  sprite.scale.x = Math.sin(performance.now() / 500);
};
```

**Related skills:** `pixijs-application` (Application setup and sharedTicker option), `pixijs-performance` (frame rate optimization), `pixijs-migration-v8` (v7 ticker signature changes).

## Core Patterns

### Time units

The Ticker exposes three timing values, each for different use cases:

| Property    | Type                          | Scaled by speed? | Capped by minFPS? | Use case                                     |
| ----------- | ----------------------------- | ---------------- | ----------------- | -------------------------------------------- |
| `deltaTime` | dimensionless (~1.0 at 60fps) | yes              | yes               | Frame-rate-independent animation multipliers |
| `deltaMS`   | milliseconds                  | yes              | yes               | Time-based calculations (pixels/sec)         |
| `elapsedMS` | milliseconds                  | no               | no                | Raw measurement, profiling                   |

```ts
import { Application } from "pixi.js";

const app = new Application();
await app.init({ width: 800, height: 600 });

app.ticker.add((ticker) => {
  // deltaTime: dimensionless scalar, ~1.0 at 60fps
  sprite.rotation += 0.1 * ticker.deltaTime;

  // deltaMS: real milliseconds (speed-scaled, capped)
  sprite.x += (200 / 1000) * ticker.deltaMS; // 200 pixels per second

  // elapsedMS: raw milliseconds (no scaling, no cap)
  console.log(`Raw frame time: ${ticker.elapsedMS}ms`);
});
```

**Tension note:** `deltaTime` is not milliseconds. It is `deltaMS * Ticker.targetFPMS` where targetFPMS is 0.06 (i.e. 1/16.67). At exactly 60fps, deltaTime is 1.0. At 30fps, deltaTime is 2.0. This catches people who treat it as a time value.

### Priority ordering and context binding

```ts
import { Application, UPDATE_PRIORITY } from "pixi.js";

const app = new Application();
await app.init({ width: 800, height: 600 });

// INTERACTION (50) > HIGH (25) > NORMAL (0) > LOW (-25) > UTILITY (-50)
// app.render() is registered at LOW by the TickerPlugin

app.ticker.add(
  (ticker) => {
    // Physics runs before normal-priority callbacks
    updatePhysics(ticker.deltaMS);
  },
  undefined,
  UPDATE_PRIORITY.HIGH,
);

app.ticker.add((ticker) => {
  // Default priority (NORMAL = 0), runs after HIGH but before render
  updateAnimations(ticker.deltaTime);
});

// Pass `this` as the second argument to preserve context on class methods
class GameSystem {
  public speed = 5;
  public position = 0;

  public update(ticker: Ticker): void {
    this.position += this.speed * ticker.deltaTime;
  }
}

const system = new GameSystem();
app.ticker.add(system.update, system);
app.ticker.remove(system.update, system); // must match both fn and context
```

### Frame rate capping

```ts
import { Ticker } from "pixi.js";

const ticker = new Ticker();

ticker.maxFPS = 30; // Cap at 30fps (skips frames to maintain interval)
ticker.minFPS = 10; // Cap deltaTime so it never exceeds 10fps worth

// If maxFPS < minFPS, minFPS is lowered to match
// If minFPS > maxFPS, maxFPS is raised to match
```

`maxFPS` skips update calls to enforce a ceiling. `minFPS` caps deltaTime/deltaMS so large frame drops don't produce enormous deltas (default minFPS is 10).

### Per-object onRender hook

```ts
import { Sprite, Assets, Application } from "pixi.js";

const app = new Application();
await app.init({ width: 800, height: 600 });

const texture = await Assets.load("bunny.png");
const sprite = new Sprite(texture);
app.stage.addChild(sprite);

sprite.onRender = (renderer) => {
  sprite.rotation += 0.01;
};
```

`onRender` is called during scene graph traversal, before GPU rendering. It is an alternative to a global ticker callback when logic is tied to a specific display object.

### Ticker.shared, Ticker.system, and new Ticker

```ts
import { Ticker, UPDATE_PRIORITY } from "pixi.js";

// Ticker.shared: singleton, autoStart=true, protected from destroy()
const shared = Ticker.shared;

// Ticker.system: separate instance used by engine background tasks,
// independent of the main scene ticker. It's a plain Ticker instance
// (autoStart=true, _protected=true) with no intrinsic priority; listeners
// are typically added at UTILITY priority by convention.
const system = Ticker.system;

// new Ticker(): custom instance, autoStart=false, you manage the lifecycle
const custom = new Ticker();
custom.autoStart = true; // start when first listener is added
custom.add((ticker) => {
  console.log(ticker.deltaMS);
});

// One-shot callback that auto-removes after firing
custom.addOnce(() => console.log("fires once"), null, UPDATE_PRIORITY.NORMAL);

// When done:
custom.stop();
custom.destroy();
```

`Application` creates its own Ticker by default. Set `sharedTicker: true` in `app.init()` to use `Ticker.shared` instead. `Ticker.shared` and `Ticker.system` are both `_protected` and will not actually be destroyed if you call `destroy()` on them. Read `ticker.FPS` for the measured frame rate and `ticker.count` for the current listener count.

### App lifecycle and manual rendering

```ts
import { Application } from "pixi.js";

const app = new Application();
await app.init({ autoStart: false });

// Pause and resume the built-in render loop at any time.
app.start();
app.stop();

// Or drive the loop yourself (headless, visibility-gated, fixed timestep, etc.)
function animate() {
  app.ticker.update(); // fires registered callbacks
  app.render(); // renders the stage
  requestAnimationFrame(animate);
}
animate();
```

`app.start()` and `app.stop()` are added by the `TickerPlugin` and map to `ticker.start()` / `ticker.stop()`. Use `autoStart: false` plus your own frame driver when you need to pause on tab blur, run a fixed-timestep loop, or render offscreen.

### Speed scaling

```ts
import { Application } from "pixi.js";

const app = new Application();
await app.init({ width: 800, height: 600 });

app.ticker.speed = 0.5; // Half speed (slow motion)
app.ticker.speed = 2.0; // Double speed

// speed affects deltaTime and deltaMS, but NOT elapsedMS
```

## Common Mistakes

### [CRITICAL] Ticker callback expects delta as first argument

Wrong:

```ts
app.ticker.add((dt) => {
  bunny.rotation += dt;
});
```

Correct:

```ts
app.ticker.add((ticker) => {
  bunny.rotation += ticker.deltaTime;
});
```

v8 passes the Ticker instance as the callback argument, not a delta number. The v7 pattern `(dt) => ...` compiles but `dt` is the entire Ticker object, so arithmetic on it produces `NaN`.


### [HIGH] Using updateTransform for per-frame logic

Wrong:

```ts
class MySprite extends Sprite {
  updateTransform() {
    super.updateTransform();
    this.rotation += 0.01;
  }
}
```

Correct:

```ts
class MySprite extends Sprite {
  constructor() {
    super();
    this.onRender = this._onRender.bind(this);
  }
  private _onRender() {
    this.rotation += 0.01;
  }
}
```

`updateTransform` was removed in v8. Use the `onRender` callback for per-object per-frame logic.


### [MEDIUM] Treating deltaTime as milliseconds

Wrong:

```ts
app.ticker.add((ticker) => {
  // Tries to move 100px/sec but deltaTime is ~1.0, not ~16.67
  sprite.x += (100 * ticker.deltaTime) / 1000;
});
```

Correct:

```ts
app.ticker.add((ticker) => {
  // Using deltaMS for time-based movement
  sprite.x += (100 / 1000) * ticker.deltaMS;
  // Or using deltaTime as a frame-rate multiplier
  sprite.x += 1.5 * ticker.deltaTime;
});
```

`deltaTime` is a dimensionless scalar (~1.0 at 60fps), not milliseconds. Use `deltaMS` for real time calculations. Use `deltaTime` as a simple multiplier when you want "per frame at 60fps" behavior.


## API Reference

- [Ticker](https://pixijs.download/release/docs/ticker.Ticker.html.md)
- [TickerPlugin](https://pixijs.download/release/docs/app.TickerPlugin.html.md)
- [TickerPluginOptions](https://pixijs.download/release/docs/app.TickerPluginOptions.html.md)

© pixijs · MIT · pixijs/pixijs-skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой