Agent skill

Pixi Vn Canvas

by DRincs-Productions in DRincs-Productions/pixi-vn

A skill your agent uses when adding, moving, or removing images, sprites, text, or video on the Pixi'VN game canvas, or when applying or creating transitions (dissolve, fade, move, zoom, push, wipe…

LGPL-2.1Auto-check passedGame Development

Install Pixi Vn Canvas

skills CLI
$ npx skills add DRincs-Productions/pixi-vn --skill pixi-vn-canvas -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install DRincs-Productions/pixi-vn pixi-vn-canvas --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/DRincs-Productions/pixi-vn.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/canvas .claude/skills/pixi-vn-canvas && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
pixi-vn-canvas
GitHub stars
149
Token cost
~7.6k tokens
SKILL.md length
2,271 words
Files
2
Skills in repo
13
Repo updated
First seen
Licence
LGPL-2.1

At a glance

A skill your agent uses when adding, moving, or removing images, sprites, text, or video on the Pixi'VN game canvas, or when applying or creating transitions (dissolve, fade, move, zoom, push, wipe…

  • Removing images
  • SKILL.md covers When to use this skill, Core mental model, Showing and removing an image and Adding text, plus 9 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Video on the PixiVN game canvas

What it does

Pixi Vn Canvas is an agent skill from DRincs-Productions/pixi-vn. Use when adding, moving, or removing images, sprites, text, or video on the Pixi'VN game canvas, or when applying or creating transitions (dissolve, fade, move, zoom, push, wipe, iris, split, flash, blur, pixelate, or a custom one built on canvas.animate/filters.animate), shake/animation effects, or ticker-based animations built on PixiJS. Covers the canvas singleton exported from @drincs/pixi-vn. For UI layers (HTML or PixiJS) mounted on top of the canvas, see pixi-vn-ui instead.

Its SKILL.md is about 7.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `tickers.md`).

It sits in Game Development, covering Sprites and pixel art. The repository describes itself as: Create visual novels with a modern 2D rendering engine and your favorite JavaScript framework.

When your agent uses it

  • Removing images
  • Video on the PixiVN game canvas
  • Creating transitions (dissolve
  • A custom one built on canvas.animate/filters.animate)

Example prompts

  • “/pixi-vn-canvas”

What it can do on your machine

Read from SKILL.md and the folder at commit 01c19cb. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • pixi-vn.com
    • motion.dev
    • github.com
    • npmjs.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Pixi Vn Canvas loads about 7.6k tokens when it runs. Until then it costs about 128 tokens; SKILL.md has 2,271 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~128
When it runs · the whole SKILL.md, loaded when a task matches
~7.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from DRincs-Productions/pixi-vn at commit 01c19cb, republished under its LGPL-2.1 licence (© DRincs-Productions). 2,271 words, ~7,586 tokens.

Download SKILL.mdSave it as .claude/skills/pixi-vn-canvas/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
pixi-vn-canvas
description
Use when adding, moving, or removing images, sprites, text, or video on the Pixi'VN game canvas, or when applying or creating transitions (dissolve, fade, move, zoom, push, wipe, iris, split, flash, blur, pixelate, or a custom one built on `canvas.animate`/`filters.animate`), shake/animation effects, or ticker-based animations built on PixiJS. Covers the `canvas` singleton exported from `@drincs/pixi-vn`. For UI layers (HTML or PixiJS) mounted on top of the canvas, see `pixi-vn-ui` instead.

Pixi'VN Canvas

The Canvas module is Pixi'VN's 2D scene graph, built directly on top of PixiJS. It manages everything that is visually rendered in the game: background images, character sprites, text, video, and the transitions/animations between them. Official docs: pixi-vn.com/start/canvas.

Every symbol used below (canvas, showImage, Sprite, transition helpers, etc.) is exported from the main package entry point:

ts
import { canvas } from "@drincs/pixi-vn";

(Also available from the narrower @drincs/pixi-vn/canvas subpath — see pixi-vn-getting-started for when to prefer that.)

When to use this skill

Load this skill whenever a task involves:

  • Showing, replacing, or removing an image/sprite/video/text on screen.
  • Building a composite character sprite out of several image layers.
  • Applying a transition (dissolve, fade, move, zoom, push, wipe, iris, split, flash, blur, pixelate) when a background or sprite changes.
  • Adding a shake effect or a custom PixiJS-ticker-driven animation.
  • Reading or modifying canvas element position/anchor/alpha/zIndex.

For building/mounting UI layers (HTML or PixiJS) on top of the canvas, use pixi-vn-ui instead — this skill is about the gameLayer save-able scene graph, not UI chrome.

For dialogue/character-portrait logic use pixi-vn-characters and pixi-vn-narration instead; this skill is about the underlying rendering primitives.

Core mental model

  • canvas (from @drincs/pixi-vn) is the single entry-point object developers use. It wraps a PixiJS Application and exposes methods to manage canvas elements and layers. Call await canvas.init(element, options) once at startup (this is normally done for you by Game.init(...) from the core package — see pixi-vn-getting-started).
  • Elements are tracked by alias, not by variable (docs). canvas.add(alias, component) inserts a component (an instance of Container, Sprite, ImageSprite, ImageContainer, Text, or VideoSprite) into canvas.layers.gameLayer (a single PixiJS Container that holds all "in-scene" elements) and sets component.label = alias. Use canvas.find<T>(alias) to look elements back up and canvas.remove(alias) to remove them. Aliases are also how Pixi'VN saves/restores canvas state (see pixi-vn-storage), so prefer the alias-based helpers below over holding onto raw object references across steps.
  • Every element class is a save-able extension of a PixiJS class: Container extends PIXI.Container, Sprite/ImageSprite/VideoSprite extend PIXI.Sprite, Text extends PIXI.Text. They add a .memory getter / .setMemory() for serialization, plus convenience properties (anchor, align, percentagePosition, xAlign/yAlign, percentageX/percentageY) as alternative ways to position an element without doing pixel math.
  • Layer is just a type alias for a plain PIXI.Container<ContainerChild> — there's no special Layer class. A separate, non-save-able PixiJS Container can be attached directly to the stage as a sibling of gameLayer (canvas.layers.add/get/remove) — see pixi-vn-ui for that API, it's how UI layers (HTML or PixiJS) are built on top of the canvas.
  • Tickers are how frame-based animation and effects work under the hood; canvas.animate(...) (built on the motion library) is the high-level way to animate numeric properties over time, and it is what all the built-in transition helpers use internally. Running tickers are managed through the separate tickers singleton (also from @drincs/pixi-vn, not a member of canvas — the old canvas.tickers is a deprecated alias of it).

Showing and removing an image

ts
import { canvas, addImage, showImage } from "@drincs/pixi-vn";

// addImage() creates + registers the sprite but does NOT load/display the texture yet
const bunny1 = addImage("bunny1"); // "bunny1" is an alias registered in the assets manifest
await bunny1.load();

// showImage() is addImage() + load() in one call
const bunny2 = await showImage("bunny2");
bunny2.anchor = 0.5;
bunny2.x = canvas.width / 2;
bunny2.y = canvas.height / 2;

// remove it later by alias
canvas.remove("bunny1");

Always pass a manifest alias (as above), not a raw URL/path — see pixi-vn-assets for how assets get registered (local vs. online) and loaded. addImage/showImage do also accept a raw URL as a second argument for quick prototyping, but that couples code to a specific file location; addImage/showImage throw a PixiError if neither a URL nor a registered alias resolves. Both return an ImageSprite.

For a composite image made of multiple stacked textures (e.g. a character body + outfit + face), use ImageContainer via addImageCointainer / showImageContainer (note the exported spelling "Cointainer"):

ts
import { showImageContainer } from "@drincs/pixi-vn";

const liam = await showImageContainer("liam", ["liam-body", "liam-head"]);

Adding text

ts
import { showText } from "@drincs/pixi-vn";

showText("score-label", "Score: 0", {
  fontSize: 24,
  fill: "white",
  x: 20,
  y: 20,
});

showText(alias, text, options) creates/replaces a Text element (extends PIXI.Text) and adds it to the canvas immediately. options is TextOptions (PixiJS CanvasTextOptions plus the align/percentagePosition positioning extensions), so style, fontSize, fill, x/y, etc. all work as in plain PixiJS.

Playing a video

ts
import { showVideo } from "@drincs/pixi-vn";

const film = await showVideo("intro-film"); // "intro-film" resolves via the assets manifest
film.loop = true;
// film.pause(), film.play(), film.restart(), film.currentTime = 2

addVideo/showVideo mirror addImage/showImage and return a VideoSprite (extends ImageSprite). Files are also recognized as videos by extension automatically anywhere a transition helper accepts an image URL (.mp4, .webm, .mov, etc. — see checkIfVideo).

Transitions

Docs: pixi-vn.com/start/canvas-transition.

All transition helpers take (alias, componentOrUrl?, props?, priority?). If you omit the component/URL argument, the alias itself is used as the texture URL/alias. Each function replaces (or removes) whatever is currently registered under alias, transferring position and running tickers from the old element automatically. They all return a Promise (or array) of ticker ids you can pass to tickers.forceCompletion if you need to await completion, but usually you just call and move on.

ts
import {
  showWithDissolve,
  removeWithDissolve, // fade the new image in / fade the current one out
  showWithFade,
  removeWithFade, // cross-fade old -> new (falls back to dissolve if none exists)
  moveIn,
  moveOut, // slide in/out from a screen edge
  zoomIn,
  zoomOut, // scale in/out from a screen edge
  pushIn,
  pushOut, // new image pushes the old one off-screen
} from "@drincs/pixi-vn";

// change background with a 1s dissolve ("bg-forest" is a manifest alias)
await showWithDissolve("background", "bg-forest", { duration: 1 });

// slide a character sprite in from the left
await moveIn("liam", "liam-neutral", { direction: "left", duration: 0.5 });

// remove a character with a zoom-out toward the right edge
zoomOut("liam", { direction: "right", duration: 0.5 });

props extends AnimationOptions from motion (e.g. duration, ease) plus a completeOnContinue flag (default true) that finishes the transition immediately when the player advances the narration before the animation ends — leave this at its default unless you specifically want an animation to be interruptible/ignored.

Generic reveal/filter transitions: wipe, iris, split, flash, blur, pixelate, glitch, twist, warp, ripple, noiseDissolve, tv, pinch

These are only exposed through the transitions namespace (no flat top-level export like the older moveIn/showWithDissolve), each as a matched xIn/xOut pair with the same (alias, componentOrUrl?, props?, priority?) / (alias, props?, priority?) shapes as above. They favor a handful of configurable options over narrative-specific variants — e.g. there's one wipeIn, not wipeLeft/wipeRight.

ts
import { transitions } from "@drincs/pixi-vn";

// wipe: a moving boundary reveals/conceals the image. `angle` in degrees (0 = left-to-right, 90 =
// bottom-to-top, ...); `direction` ("up"/"down"/"left"/"right") is a shorthand for the 4 cardinal angles.
await transitions.wipeIn("background", "bg-forest", { direction: "left", duration: 1 });
await transitions.wipeIn("background", "bg-night", { angle: 45, duration: 1 }); // diagonal wipe
transitions.wipeOut("background", { angle: 180, invert: true, duration: 1 });

// iris: an expanding/contracting radial mask. `origin` is normalized (0-1) to the element's own bounds.
await transitions.irisIn("liam", "liam-happy", { origin: { x: 0.5, y: 0.3 }, duration: 0.8 });
transitions.irisOut("liam", { aspect: 2, duration: 0.8 }); // aspect > 1 = wide ellipse instead of a circle

// split: two mask panels move apart/together - covers "curtain" effects without a dedicated API.
await transitions.splitIn("background", "bg-forest", { orientation: "horizontal", duration: 1 });
transitions.splitOut("background", { orientation: "vertical", origin: 0.3, duration: 1 });

// flash: a configurable color overlay (not just white) fades in/hold/out, optionally pulsing.
await transitions.flashIn("background", "bg-forest", { duration: 0.15 }); // white camera-flash reveal
transitions.flashOut("liam", { color: 0xff0033, holdDuration: 0.05, pulses: 3, duration: 0.1 }); // red damage flash

// blur / pixelate: the image is shown already blurred/pixelated and resolves into focus (or the reverse for *Out).
await transitions.blurIn("liam", "liam-happy", { strength: 40, duration: 1 });
transitions.blurOut("liam", { duration: 1 });
await transitions.pixelateIn("background", "bg-forest", { pixelSize: 48, duration: 1 });
transitions.pixelateOut("background", { duration: 1 });

// glitch: jittery slices + red/blue split, settling on *In, building up on *Out.
await transitions.glitchIn("liam", "liam-happy", { strength: 40, bursts: 3 });
// twist: unwinds out of (or winds into) a swirl - `angle` in degrees, `origin` normalized.
transitions.twistOut("liam", { angle: 540 });
// warp: radial zoom-blur streaks, like dropping out of / jumping into hyperspace.
await transitions.warpIn("background", "bg-space", { strength: 0.6 });
// ripple: fades in/out through a spreading water ring - dreams, magic, memories.
await transitions.rippleIn("liam", "liam-dream", { origin: { x: 0.5, y: 0.3 } });
// noiseDissolve: the classic VN image dissolve - organic noise blotches (`edge: "soft"` for a cloudy fade).
await transitions.noiseDissolveIn("background", "bg-night", { edge: "hard", noiseScale: 8 });
// tv: old TV switching on (dot -> glowing line -> image) / off; scales around the anchor (center it).
transitions.tvOut("liam", { lineThickness: 0.02, brightness: 3 });
// pinch: emerges from / is sucked into a point (`mode: "bulge"` puffs out instead).
transitions.pinchOut("liam", { mode: "pinch" });

// move/push also take an optional motion-blur trail (true = 40px, or a length in pixels).
await transitions.moveIn("liam", "liam-happy", { direction: "right", duration: 0.6, motionBlur: true });

Distortion transitions (glitch, twist, warp, ripple, pinch) move pixels around, so they read best on images with detail - on a flat, single-color element they're much less visible.

They compose freely since each drives its own mask (wipe/iris/split) or filter (blur/pixelate/glitch/...) independently — e.g. call blurIn and then wipeIn on the same alias to combine both. Common narrative effects are just recipes built from these primitives rather than dedicated functions: a "blink"/eyes-opening effect is a color overlay plus an iris reveal, a "dream"/flashback is blurIn + showWithFade, a memory transition is a color overlay plus blurIn, a "curtain" is a configured splitOut, and a diagonal wipe is just wipeIn/wipeOut with a non-cardinal angle.

Creating custom transitions

Docs: pixi-vn.com/start/canvas-transition#custom-functionality.

A custom transition is just a plain function that adds/replaces a component and drives it with canvas.animate — the same primitive showWithDissolve, moveIn, etc. are built on:

ts
import { canvas, ImageSprite, UPDATE_PRIORITY } from "@drincs/pixi-vn";
import { AnimationOptions } from "@drincs/pixi-vn/motion";

export default async function showWithDissolve(
  alias: string,
  component: ImageSprite,
  props: AnimationOptions = {},
  priority?: UPDATE_PRIORITY,
): Promise<string[] | undefined> {
  const { completeOnContinue = true, ...options } = props;
  canvas.add(alias, component);
  component.alpha = 0;
  const id = canvas.animate(alias, { alpha: 1 }, { ...options, completeOnContinue }, priority);
  if (component.haveEmptyTexture) await component.load();
  if (id) return [id];
}

If a component under the same alias may already exist, either let canvas.add replace it outright (per the heredity-factor gotcha above), or explicitly swap it in first — rename the old component's alias, add the new one, restore z-order, then transfer its properties/tickers — so an in-flight animation on the old element carries over instead of snapping:

ts
let oldComponentAlias: string | undefined;
const oldComponent = canvas.find(alias);
if (oldComponent) {
  oldComponentAlias = `${alias}_temp`;
  canvas.editAlias(alias, oldComponentAlias);
}
canvas.add(alias, component);
oldComponent?.parent?.setChildIndex(oldComponent, oldComponent.parent.getChildIndex(oldComponent) - 0.1);
oldComponentAlias && canvas.copyCanvasElementProperty(oldComponentAlias, alias);
oldComponentAlias && tickers.transfer(oldComponentAlias, alias, "duplicate");

To remove the old component only once the new one's transition finishes, pass aliasToRemoveAfter: oldComponentAlias in canvas.animate's options instead of removing it manually. To have the old component run its own transition-out (instead of a hard cut), give it a second canvas.animate call paused with tickers.pause({ id }) and resumed via the new call's tickerIdToResume option — see the wiki's own two worked examples for the exact sequencing.

Animating a filter's own property instead of a component property — for effects like blur, pixelate, glow, or color grading, use filters.animate (from @drincs/pixi-vn/filters, available since v1.9.4) instead of canvas.animate. It mirrors the same (alias, keyframes, options, priority) shape with the Filter instance inserted as the second argument; you attach the filter to component.filters yourself before animating, and detach + destroy it in the cleanup callback (the 7th argument) once the animation completes — this is exactly how transitions.blurIn/blurOut/pixelateIn/pixelateOut are implemented:

ts
import { canvas, ImageSprite, UPDATE_PRIORITY } from "@drincs/pixi-vn";
import { filters } from "@drincs/pixi-vn/filters";
import { AnimationOptions } from "@drincs/pixi-vn/motion";

export default async function blurIn(
  alias: string,
  component: ImageSprite,
  props: AnimationOptions & { strength?: number } = {},
  priority?: UPDATE_PRIORITY,
): Promise<string[] | undefined> {
  const { strength = 32, completeOnContinue = true, ...options } = props;
  canvas.add(alias, component);
  const filter = new filters.BlurFilter({ strength });
  component.filters = [filter];
  const id = filters.animate(
    alias,
    filter,
    { strength: [strength, 0] },
    { ...options, completeOnContinue },
    priority,
    undefined, // apply - only needed when filter is undefined (see below)
    () => {
      component.filters = null;
      filter.destroy();
    },
  );
  if (component.haveEmptyTexture) await component.load();
  if (id) return [id];
}

filters.animate can also drive a plain numeric value with no live filter — pass undefined as the filter and an apply callback (called every frame with the interpolated value) instead. This is how wipeIn/irisIn/splitIn animate their mask geometry (a growing radius, a moving boundary), since a mask has no filter property to write directly.

Shake and other articulated animations

The effects namespace holds "articulated animations" — helpers built on top of canvas.animate that bake a full keyframe array once and animate it in a single call (docs: canvas-articulated-animations-effects, canvas-motion). Like the transitions above, these are generic primitives — the effect describes how a component moves, the game decides what that means (a hit reaction, an idle fidget, an emphasis beat, ...).

ts
import { effects, canvas } from "@drincs/pixi-vn";

// shake a canvas element horizontally
await effects.shakeEffect("screen-flash-target", {
  shakeType: "horizontal",
  maxShockSize: 15,
  shocksNumber: 10,
});

// bounce: one-directional decaying displacement, e.g. a character landing a jump
await effects.bounceEffect("liam", { direction: "up", distance: 30, bounces: 3 });

// pulse: decaying scale bump, e.g. emphasizing a UI element or a heartbeat
await effects.pulseEffect("liam", { scale: 1.3, pulses: 2 });

// hop: a single displacement-and-return, optionally with smaller decaying follow-up hops
await effects.hopEffect("liam", { direction: "up", distance: 40, secondaryHops: 2 });

// wiggle: decaying rotation oscillation, e.g. a "no" head-shake or a nervous tic
await effects.wiggleEffect("liam", { angle: 15, repetitions: 3 });

// nod: decaying positional oscillation along one axis, e.g. a "yes" nod or a flinch
await effects.nodEffect("liam", { axis: "vertical", distance: 10, repetitions: 3 });

// sway: smooth combined position+rotation drift, e.g. an idle breathing/swaying loop
// (decay defaults to 0 = constant amplitude, unlike the other primitives above)
await effects.swayEffect("liam", { distance: 8, angle: 3, repetitions: 4 });

// punch: a single fast impulse with a settle-back overshoot, e.g. taking a hit
await effects.punchEffect("liam", { mode: "scale", strength: 0.3, overshoot: 0.3 });
await effects.punchEffect("liam", { mode: "rotation", strength: 20 });

// low-level: animate arbitrary numeric properties with motion-style keyframes
canvas.animate("liam", { alpha: [0, 1], y: [50, 0] }, { duration: 0.8 });

There's no separate "tremble"/"vibration" primitive — that's just shakeEffect configured with a small maxShockSize and a high shocksNumber (high-frequency, low-amplitude shaking).

Show full SKILL.md (974 more words)Show less

Filter-based articulated animations

The same effects namespace also has primitives built on the filters module (raw pixi-filters/ pixi.js filter classes, re-exported as filters.* - see @drincs/pixi-vn/filters) instead of canvas.animate: each one attaches a filter to the component, drives one of the filter's own properties through a decaying (or one-shot) keyframe array via filters.animate, and detaches/destroys the filter once done - the component is left exactly as it was before, same guarantee as every effect above.

ts
import { effects } from "@drincs/pixi-vn";

// glitch: jittery, decaying bursts of slice displacement with a matching red/blue channel split
// (returns two ticker ids; `rgbSplit: 0` drops the channel split)
await effects.glitchEffect("liam", { strength: 40, bursts: 3, rgbSplit: 6 });

// chromaticAberration: red/blue channels split apart and snap back, in a decaying burst
await effects.chromaticAberrationEffect("liam", { strength: 8, axis: "horizontal" });

// shockwave: a single ripple distortion travels outward from `origin` (normalized to the element's
// bounds) - by default until it has fully left the element
await effects.shockwaveEffect("liam", { origin: { x: 0.5, y: 0.5 } });

// radialBlur: a decaying burst of zoom-blur radiating from `origin` (normalized to the element's bounds)
await effects.radialBlurEffect("liam", { strength: 0.3, bursts: 1 });

// blurPulse: a repeated, decaying blur bump (distinct from blurIn/blurOut, which are one-shot
// reveal/conceal transitions, not a repeated pulse)
await effects.blurPulseEffect("liam", { strength: 8, pulses: 3 });

// vignettePulse: the edges darken and recover, in a repeated, decaying pulse - it darkens the corners
// of the element's own rectangle, so use it on backgrounds/full-frame images, not on characters
await effects.vignettePulseEffect("background", { strength: 1, pulses: 1, radius: 0.5 });

// desaturate: color drains out and recovers - a single dip, not a repeated pulse
await effects.desaturateEffect("liam", { amount: 0, holdDuration: 0.2 });

// glowPulse: a repeated, decaying outward glow
await effects.glowPulseEffect("liam", { strength: 4, pulses: 3, color: 0xffee00 });

All 8 are per-component (same alias pattern as everything else here) - there's no screen-wide/global filter effect yet. Distortion effects (glitch, chromatic aberration, shockwave, radial blur) move pixels around, so they only read on an image with detail/edges - on a flat, single-color element they look like nothing happened. Build a custom one the same way: construct any filters.* class, attach it to component.filters yourself, and drive it with filters.animate (see the low-level example just above this section) - AdjustmentFilter/HslAdjustmentFilter (color grading), CRTFilter/OldFilmFilter (retro looks), and BloomFilter/AdvancedBloomFilter (glow) are good starting points not covered above.

canvas.animate(componentOrAlias, keyframes, options, priority) is the primitive all transition helpers are built on (motion's animate semantics: keyframes are arrays of target values, options supports duration, ease, repeat, etc.). Pixi'VN tracks animation state so it can be saved/restored — this is why you should prefer canvas.animate (or the transition helpers) over driving PixiJS directly with your own requestAnimationFrame loop. For UI that is not part of the saved scene graph (e.g. a PixiJS UI overlay), the docs recommend importing the raw animate from @drincs/pixi-vn/motion instead — it skips the save-state bookkeeping and is cheaper.

Frame tickers

canvas.animate and the transition helpers above already use tickers internally — most tasks never need to touch the ticker API directly. For a genuinely continuous/looping custom effect (no fixed duration) or manual pause/resume/completion control over a running animation, see tickers.md in this same skill folder (registering a Ticker, tickers.addSequence, tickers.pause/resume/remove, tickers.completeOnStepEnd). Docs: pixi-vn.com/start/canvas-tickers.

External rendering plugins

These optional packages are installed separately from @drincs/pixi-vn; their component classes must be imported from the plugin, not the engine. Check the installed package's peer dependencies and types before adapting examples to a project's PixiJS/Pixi'VN versions.

Live2D: @drincs/pixi-vn-live2d

Use this wrapper around untitled-pixi-live2d-engine for Live2D models. Register its render plugin before Game.init() (or canvas.init()):

ts
import { extensions } from "pixi.js";
import { Live2DPlugin } from "@drincs/pixi-vn-live2d/core";

extensions.add(Live2DPlugin);
// Initialize the game/canvas after registering the plugin.

Once the canvas is initialized, register the model asset and await model readiness before controlling it:

ts
import { Assets, canvas } from "@drincs/pixi-vn";
import { Live2D } from "@drincs/pixi-vn-live2d";

Assets.add({ alias: "hero-model", src: "/models/hero/model3.json" });
const model = new Live2D({ source: "hero-model" });
await model.ready;
model.motion("Idle"); // Use a motion group present in this model.
canvas.add("hero", model);

Consult the plugin README for setup and its API reference for model options. Do not substitute ImageSprite.load() for Live2D.ready.

Spine: @drincs/pixi-vn-spine

Use this wrapper around @esotericsoftware/spine-pixi-v8 for skeletal animation. Add import "@drincs/pixi-vn-spine"; to the app entry point: importing the package registers the serializable component. A lazy scene import alone is insufficient when a save is restored before that scene has ever loaded.

Register the skeleton and atlas in the asset manifest, then load both before construction:

ts
import { Assets, canvas } from "@drincs/pixi-vn";
import { Spine } from "@drincs/pixi-vn-spine";

await Assets.load(["hero-skeleton", "hero-atlas"]);
const model = new Spine({ skeleton: "hero-skeleton", atlas: "hero-atlas" });
model.setAnimation(0, "idle", true); // Animation names come from the skeleton.
canvas.add("hero", model);

See the Spine guide for skins and tracks and the package README for save-registration details. Keep the Pixi'VN wrapper when adding saved scene elements.

UI layers

Persistent UI chrome (HUD, menus) does not live on gameLayer — it lives on a separate, non-save-able layer built with canvas.layers.add/get/remove (PixiJS-only UI) or canvas.htmlLayers.add/get/remove (mounting a DOM-based UI framework like React or Vue). That whole API, plus the official template's layer-naming conventions, extractImage() for save-file thumbnails, and how to build a UI purely out of PixiJS components, is covered by pixi-vn-ui — reach for that skill instead whenever the task is about UI rather than the game scene.

Gotchas

  • addImage/addVideo/addImageCointainer only construct and register the element — the texture is not loaded/visible until you await element.load(). The show* variants (showImage, showVideo, showImageContainer, and the transition helpers) call load() for you; prefer them unless you need to prepare an element off-screen first.
  • getTexture/load() throw a PixiError (unregistered_asset) if the alias can't be resolved from the PixiJS Assets cache/manifest. See pixi-vn-assets for how to register an alias (local assets via AssetPack, or online assets in src/assets/index.ts) before referencing it here.
  • Adding an element with an alias that already exists replaces it and — per the "heredity factor" — copies over properties/zIndex/tickers from the old one by default (canvas.add(alias, el, { ignoreOldStyle: true }) to opt out) — this is what lets showImage("bg", newUrl) "just work" as a same-alias swap.
  • canvas.remove(alias) also removes tickers bound only to that alias; pass { ignoreTickers: true } if you intend to reattach them elsewhere first.
  • Event listeners use plain PixiJS .on(...), not a Pixi'VN-specific method — a stray JSDoc comment in the Sprite source suggests sprite.onEvent(...), but that method doesn't exist; the official docs confirm .on(...) is correct. The Pixi'VN-specific part is only the @eventDecorator() requirement for save/load: sprite.on("pointerdown", Events.handler) only serializes correctly if Events.handler is a static method decorated with @eventDecorator() (from @drincs/pixi-vn); a plain inline arrow function will log a warning and not be restored after loading a save.
  • Positioning has multiple parallel systems (docs: canvas-position) — pixel (x/y/position), anchor/pivot (where on the element itself the position point sits), align/xAlign/yAlign (Ren'Py-style percentage-of-canvas positioning, e.g. 0.5 = centered; per source JSDoc, pivot does not affect align), and percentagePosition/percentageX/percentageY (also percentage-of-parent, but pivot does affect it, unlike align). Setting x/align/percentagePosition on the same axis clears the others; check element.positionType / element.positionInfo if you need to know which mode is active.
  • CANVAS_APP_GAME_LAYER_ALIAS ("__game_layer__") is reserved — canvas.add, remove, and addLayer will refuse to use that alias.
  • canvas.pause()/canvas.resume() stop/restart rendering and tickers for the whole game layer (e.g. when opening a menu) — remember to call resume() or elements will appear frozen.
  • pixi-vn-getting-started: project setup, Game.init(), and how the canvas is wired up at startup.
  • pixi-vn-assets: registering images/video (local or online) and choosing when their bundle loads, before referencing them here by alias.
  • pixi-vn-characters: character/emotion definitions that use canvas images under the hood for portraits.
  • pixi-vn-narration: dialogue/step flow, and how canvas transitions integrate with completeOnContinue.
  • pixi-vn-storage: how canvas element state (by alias) is saved and restored across game saves.
  • pixi-vn-ui: building/mounting UI layers (HTML or PixiJS) on top of the canvas — addLayer, addHtmlLayer, and building UI screens with PixiJS components.

© DRincs-Productions, LGPL-2.1. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file in skills/canvas of DRincs-Productions/pixi-vn.

  • SKILL.md
  • tickers.md

Open the folder on GitHubat commit 01c19cb

Compare with similar skills

Pixi Vn Canvas next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Pixi Vn Canvas compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Pixi Vn Canvas this skillDRincs-Productions/pixi-vn149—~7.6kAutomated safety check: PassLGPL-2.1
Game Asset Generatorhtdt/godogen7.1k—~2.8kAutomated safety check: PassMIT
Code-Drawn 2D Game Art0x0funky/agent-sprite-forge4.4k—~2.5kAutomated safety check: PassMIT
Sprite Genaldegad/sprite-gen2.7k—~4.9kAutomated safety check: PassApache-2.0
Pixel Artmateaix/mateclaw1.2k5 repos~1.8kAutomated safety check: PassApache-2.0
Petdexcrafter-station/petdex4.2k—~614Automated safety check: PassMIT

Similar skills

  • Generates game art from text prompts: PNG images, GLB 3D models, rigged characters, animations and sprites, with background removal.

    7.1k GitHub stars~2.8k tokensUpdated 9 days ago
    Game DevelopmentAuto-check passed
  • Code-Drawn 2D Game Art

    0x0funky/agent-sprite-forge

    Draws 2D game art from code with no image model: pixel sprites, SVG props and icons, rigged characters, FX, autotiles and layouts, only when explicitly asked for.

    4.4k GitHub stars~2.5k tokensUpdated 5 days ago
    Game DevelopmentAuto-check passed
  • Sprite Gen

    aldegad/sprite-gen

    Generates images and game sprites through GPT or Grok with guided provider choices, separate saved defaults, automatic cleanup and optional curation.

    2.7k GitHub stars~4.9k tokensUpdated 2 days ago
    Game DevelopmentAuto-check passed
  • Pixel Art

    mateaix/mateclaw

    Pixel art w/ era palettes (NES, Game Boy, PICO-8). An agent skill from mateaix/mateclaw.

    1.2k GitHub starsUsed in 5 repos~1.8k tokens
    Game DevelopmentAuto-check passed
  • Petdex

    crafter-station/petdex

    Browse, install, submit, and edit pixel-art pets with the Petdex CLI.

    4.2k GitHub stars~614 tokensUpdated today
    Game DevelopmentAuto-check passed
  • Asset Pipeline

    rehan-remade/universal-modder

    Turn generated or hand-made art into exactly what a game engine loads.

    6.5k GitHub stars~2k tokensUpdated today
    Game DevelopmentAuto-check passed

More from DRincs-Productions/pixi-vn

All 13 skills in this repo
  • Pixi Vn Assets

    DRincs-Productions/pixi-vn

    A skill your agent uses when adding, organizing, registering, or loading non-code files (images, audio, video) in a Pixi'VN project — local assets processed by PixiJS AssetPack vs.

    149 GitHub stars~2.9k tokensUpdated 10 days ago
    Auto-check passed
  • Pixi Vn Characters

    DRincs-Productions/pixi-vn

    A skill your agent uses when defining visual novel characters for a @drincs/pixi-vn game — creating a character with a name, color, icon and other props, registering it so it can be looked up by id…

    149 GitHub stars~3.1k tokensUpdated 10 days ago
    Auto-check passed
  • Pixi Vn History

    DRincs-Productions/pixi-vn

    A skill your agent uses when implementing "go back" / "rewind" / step-navigation features in a Pixi'VN game, or when you need to read the player-facing dialogue/choice history (e.g.

    149 GitHub stars~2.6k tokensUpdated 10 days ago
    Auto-check passed
  • Pixi Vn Minigames

    DRincs-Productions/pixi-vn

    A skill your agent uses when adding a minigame (snake, quiz, puzzle, timing/reaction game, ...) to a Pixi'VN visual novel — the useMinigame lifecycle hook pattern, using PixiJS directly on its own…

    149 GitHub stars~2.9k tokensUpdated 10 days ago
    Auto-check passed
  • Pixi Vn Narration

    DRincs-Productions/pixi-vn

    A skill your agent uses when writing or editing Pixi'VN story content — defining labels (scenes) with newLabel, writing dialogue steps, adding player choices with…

    149 GitHub stars~4.9k tokensUpdated 10 days ago
    Auto-check passed
  • Pixi Vn Saves

    DRincs-Productions/pixi-vn

    A skill your agent uses when implementing save/load in a Pixi'VN game — Game.exportGameState()/restoreGameState()/jsonToGameState(), what the exported GameState contains, and how to persist it (save…

    149 GitHub stars~1.5k tokensUpdated 10 days ago
    Auto-check passed

Questions about Pixi Vn Canvas

What does Pixi Vn Canvas do?

A skill your agent uses when adding, moving, or removing images, sprites, text, or video on the Pixi'VN game canvas, or when applying or creating transitions (dissolve, fade, move, zoom, push, wipe…. Pixi Vn Canvas is an agent skill from DRincs-Productions/pixi-vn.animate), shake/animation effects, or ticker-based animations built on PixiJS.

When should I use Pixi Vn Canvas?

Pixi Vn Canvas fits situations like: removing images; video on the PixiVN game canvas; creating transitions (dissolve; A custom one built on canvas.animate/filters.animate).

How do I install Pixi Vn Canvas in Claude Code?

Run `npx skills add DRincs-Productions/pixi-vn --skill pixi-vn-canvas -a claude-code`. Or copy the skill folder (skills/canvas in DRincs-Productions/pixi-vn) into .claude/skills/pixi-vn-canvas in your project. Claude Code loads it when a task matches its description.

How do I install Pixi Vn Canvas in Codex?

Run `npx skills add DRincs-Productions/pixi-vn --skill pixi-vn-canvas -a codex`. Or copy the skill folder (skills/canvas in DRincs-Productions/pixi-vn) into .agents/skills/pixi-vn-canvas in your project. Codex loads it when a task matches its description.

Can I use Pixi Vn Canvas in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add DRincs-Productions/pixi-vn --skill pixi-vn-canvas -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/pixi-vn-canvas, .gemini/skills/pixi-vn-canvas, .github/skills/pixi-vn-canvas and .opencode/skills/pixi-vn-canvas in your project.

What does Pixi Vn Canvas need to run?

SKILL.md names no scripts, command-line tools or credentials: Pixi Vn Canvas is instructions for the agent only.

Does Pixi Vn Canvas access the network?

SKILL.md names 4 domains. As links in the text: pixi-vn.com, motion.dev, github.com and npmjs.com. This is read from the text; nothing was executed.

Is Pixi Vn Canvas safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Pixi Vn Canvas use?

Pixi Vn Canvas is published under the LGPL-2.1 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Pixi Vn Canvas use?

About 7.6k tokens (SKILL.md is roughly 30k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Pixi Vn Canvas?

Skills that share tags, products or a category with Pixi Vn Canvas: Game Asset Generator (htdt/godogen, 7.1k stars), Code-Drawn 2D Game Art (0x0funky/agent-sprite-forge, 4.4k stars), Sprite Gen (aldegad/sprite-gen, 2.7k stars) and Pixel Art (mateaix/mateclaw, 1.2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Pixi Vn Canvas?

DRincs-Productions (a GitHub organization) maintains it in DRincs-Productions/pixi-vn, which has 149 GitHub stars. The repository holds 13 skills in this directory. The repository was last updated on October 1, 2026.

Source: DRincs-Productions/pixi-vn on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.