add-game
무료Add a second game to the monorepo (apps/<game>) from the seed game, wired to the gate. Load when asked to create a new game / app / prototype in this repo.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
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.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
실행 점수 미검증
설치 방법 보기설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
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.
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).
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 |
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.
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
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).
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.
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.
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.
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
Wrong:
app.ticker.add((dt) => {
bunny.rotation += dt;
});
Correct:
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.
Wrong:
class MySprite extends Sprite {
updateTransform() {
super.updateTransform();
this.rotation += 0.01;
}
}
Correct:
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.
Wrong:
app.ticker.add((ticker) => {
// Tries to move 100px/sec but deltaTime is ~1.0, not ~16.67
sprite.x += (100 * ticker.deltaTime) / 1000;
});
Correct:
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.
아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
Add a second game to the monorepo (apps/<game>) from the seed game, wired to the gate. Load when asked to create a new game / app / prototype in this repo.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
End-to-end tests of a game with Playwright (apps/*/e2e/*.e2e.ts) on a WebGL canvas, and taking screenshots of the running game. Load before writing or debugging an e2e test, or to look at the game in a browser.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
How a game of this seed is organized (apps/<game>/src) and how to add gameplay with PixiJS v8 without breaking the strict gate. Load before editing apps/*/src or apps/*/tests.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use this skill first for ANY PixiJS v8 task; it routes to the right specialized skill for the job. Covers the full PixiJS surface: Application setup, the scene graph (Container, Sprite, Graphics, Text, Mesh, ParticleContainer, DOMContainer, GifSprite), rendering (WebGL/WebGPU/Canvas, render loop, custom shaders, filters, blend modes), assets, events, color, math, ticker, accessibility, performance, environments, migration from v7, and project scaffolding. Triggers on: pixi, pixi.js, pixijs, PixiJS, v8, Application, app.init, Sprite, Container, Graphics, Text, Mesh, ParticleContainer, DOMContainer, GifSprite, Assets, Ticker, renderer, WebGL, WebGPU, scene graph, filter, shader, blend mode, texture, BitmapText, create-pixi, how do I draw, how do I render, how do I animate in pixi.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use this skill when adding screen reader and keyboard navigation to PixiJS v8 apps. Covers AccessibilitySystem options (enabledByDefault, debug, activateOnTab, deactivateOnMouseMove), per-container accessibility properties, shadow DOM overlay, mobile touch-hook activation. Triggers on: accessibility, a11y, screen reader, ARIA, keyboard navigation, tab order, AccessibilitySystem, accessibleTitle, accessibleHint, tabIndex, accessibleChildren.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use this skill when creating and configuring a PixiJS v8 Application. Covers new Application() + async app.init() options (width, height, background, antialias, resolution, autoDensity, preference, resizeTo, autoStart, sharedTicker, canvas, useBackBuffer, powerPreference, eventFeatures, accessibilityOptions, gcActive, bezierSmoothness, webgl/webgpu/canvasOptions per-renderer overrides), app.stage/renderer/canvas/screen/domContainerRoot access, ResizePlugin, TickerPlugin, CullerPlugin (cullable, cullArea), custom ApplicationPlugin via ExtensionType.Application, start/stop lifecycle, and app.destroy() with releaseGlobalResources. Triggers on: Application, app.init, app.stage, app.renderer, app.canvas, app.screen, app.domContainerRoot, ApplicationOptions, ApplicationPlugin, ExtensionType.Application, resizeTo, sharedTicker, skipExtensionImports, preferWebGLVersion, preserveDrawingBuffer, cullable, CullerPlugin, app.start, app.stop, app.destroy, releaseGlobalResources.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.