pixel-game-vfx

Verified@baize/pixel-game-vfx
Use it in Cohub

Paste this into your agent's chat — it fetches the skill and follows it.

Use the skill: pixel-game-vfx. Run `npx -y @neta-art/neta-search-cli@latest skills use @baize/pixel-game-vfx --via site` and follow what it prints. Read its complete output, redirecting it to a temporary file first if necessary, and resolve relative paths from the skill directory it prints.
Use in Neta Studio Open it in Neta Studio and see what people made with it.
Install from a terminal
npx -y @neta-art/neta-search-cli@latest skills use @baize/pixel-game-vfx
Summary

Get pixel-art game effects, from fire to heals, played live on a page, with your character performing the move.

  • Pick from 244 ready-made effects: fire, explosions, ice, lightning, sword slashes, magic, heals, rain, cherry blossoms, coin pickups, chest opening, screen transitions and small creatures.
  • For a character, you get one signature move per run. Your own character winds up, strikes and recovers, and the target freezes briefly on impact.
  • For a place or a game moment, you get a set of 3 to 6 effects. A harbour gets rain and ripples, for example.
  • Recolor any effect, such as blue fire or a pink heal. If nothing fits, a brand-new effect can be made for you.
  • You get a web page with every effect playing live, slow motion, GIFs, and transparent frame sheets for Godot, Unity or Phaser, plus a zip of everything.
SKILL.md
# pixel-game-vfx: pixel game effects, ready-made or made to order

Read this whole file before acting.

The effects come from **pixelfx** (`pixelfx/` in this skill's folder, MIT, upstream commit in `pixelfx/UPSTREAM`).
Each effect is one small JS file, `pixelfx/src/fx/<category>/<name>.js`, that draws pixels in code: no images, so it
can be recolored, mirrored, reseeded, played live in a browser and baked into a sprite sheet for any engine.

`<skill-dir>` = the folder this SKILL.md sits in (the directory `skills use` printed). The tools need only Node.

**Deliverable: one web Work** — a grid of the chosen effects playing live; tapping one opens it big with its timing
(wind-up, hit freeze, recovery), slow motion and its files (transparent sprite sheet PNG + JSON, the whole act with
the character, a GIF, code for a browser game); one "download all" zip. `tools/build-page.mjs` builds it from a small `page.json`.

Reply in the user's language. Text the user sees in the deliverable — Work title, page title, effect titles and
notes — follows the user's language (`page.json` `lang`: `en`, `zh`, `ja`, `ko`, `es` or `de`; the page's buttons
come from its own table for that language).

## 0. Decide what to make

Two kinds of run. Decide which from the request and the selected card, then follow it to delivery.

**A. A character's move — one move per run.** The ask is about a character of this world (a selected or named
character card) who stands on two legs (people, upright mascots and creatures). Each run makes **one move**,
played by the character itself (section 1b), and adds it to that character's page; the next move is a next run.

1. **Which move.** Named in the request or by the menu entry ("rasengan", "a fireball", "his hammer slam") → that
   one, no question. Not named ("skill effects for X", "make X's moves") → ask once (0.1), then build. No character named
   either ("my character's skills") → the same round asks who.
2. **Colors.** Asked for → that. Otherwise the character's element or signature colours from the card.

**B. A set of effects — no questions.** A place, a game moment, no character, or a four-legged / flying / swimming
creature: 3 to 6 effects in one run, the stock dummy where an effect has a body.

1. **Which effects.** Named → those. A place → its weather and ambience (a harbour: `weather/rain`,
   `water/ripples`, `critters/bird`; a shrine: `weather/cherry-blossoms`, `weather/fireflies`). A game moment → that
   moment (`ui/coin-collect`, `pickups/chest-open`, `ui/level-up`, a `transitions/*`). Nothing to go on → a starter
   set: `melee/sword-slash`, `explosions/small-explosion`, `holy/heal`, `ui/coin-collect`, `pickups/chest-open`.
2. **Colors.** Asked for → that; else from the world's theme; else the effect's own.

The engine is never a question: the page offers sprite sheets and code. Mention the files for the engine the user named.

### 0.1 Which move (character runs where none was named)

One round with the platform questionnaire, before any generation (each move costs one image): read the card first,
then follow [`references/questionnaire.md`](references/questionnaire.md) — picture tiles of 4 to 6 of the
character's own moves (each shows a preview of the effect it is built on), and the colours when those are open.
Keep the options not picked: they are the next-steps offers at the end.

## 1. Find the effects

```bash
cd <skill-dir>/pixelfx
node tools/list.mjs frost              # searches ids, names, tags, descriptions (English words)
node tools/list.mjs slash loop     # several words must all match; search one word at a time when unsure
```

`pixelfx/docs/CATALOG.md` lists all 244 by category: `moves` (whole attacks with a character: wind-up → release →
hit → recovery), `fire`, `explosions`, `water`, `ice`, `lightning`, `scifi`, `melee`, `impacts`, `projectiles`,
`spawn` (spawn and death), `arcane`, `holy`, `shadow`, `status` (burning, frozen, poisoned, charmed…), `nature`,
`weather`, `ui`, `pickups`, `transitions`, `critters`. Translate the user's words to English to search.

To look at a candidate before choosing (the tools write to `records/` unless given `--out`):

```bash
node tools/render.mjs ice/frost-nova --out /tmp/pvfx            # -> /tmp/pvfx/ice/frost-nova/contact.png
node tools/act.mjs melee/sword-slash --out /tmp/pvfx/slash.png  # acted out, consecutive 12 fps steps
```

Open the PNG with your image-reading tool.

**Options** (all go in the item's `opts`):

- `palette` — the main color ramp, **dark to bright**, hex strings, any length. For "blue fire" use a navy → blue →
  cyan → white ramp, not one flat blue. Named ramps (`PAL` in `pixelfx/src/core/color.js`): fire ember lava smoke
  dust ice water electric volt poison holy heal arcane shadow blood earth stone gold leaf wood metal bone neon cyber
  matrix candy night — copy their hex values.
- On-body effects (heals, buffs) sit on a pale grey character: give them a saturated ramp (the pink one in step 2),
  or a light one reads as white.
- `palette` recolors the **main** ramp only. Other colors are either their own options in the effect's
  `meta.options` (`stone`, `smoke`, `dust`… pass them too) or fixed in code (an arrow's shaft, an egg, a critter's
  body, and the flames of the shared fire simulation used by some explosions). So look at the recolor (step 2's
  check) and, if something the user cares about stayed orange, recolor it in a lab copy (section 3) or pick another.
- `flip` (face left), `angle`, `seed` (a different but equivalent take), `light` (glow, 0..1+), and the effect's own
  knobs in its `meta.options` (size, count, radius, text…). Read the file's `meta` to see them.

**The 12 `moves` take no `palette`**: a move chains several effects, each with its own colors. To recolor one, make a
variant in a lab copy (section 3): copy the move file to a new name, add `palette: <ramp>` to each cue in its
`chain([...])` (and the effect's other color options, e.g. `stone`), and build with `--lib`. `build-page.mjs` warns
when an effect ignores an option you passed.

## 1b. Character runs: the character plays the move

The move is **one item with an act** (wind-up, release, hit, recovery), and the character's own action is made
**for this move**: one generated image, about 1–1.5 minutes (say so in the reply). The frames come from the
`side-sprite-actions` skill; pixel-game-vfx scales them to its pixel grid and plays them on the effect's clock.

1. **The effect.** The closest library effect with an `act` (a `moves/*` for throws, combos, casts; `melee/*` for
   weapon hits; `holy/*`, `status/*`, `arcane/blink-*` for things that happen on the body). A move whose closest
   effect has no act (a projectile or an impact alone) becomes a lab move (section 3): copy the nearest `moves/*`
   (`moves/fireball-throw` for anything thrown) and swap its cues, so the character throws it.
2. **The action, made for this move.** Reuse `works/web*/<character-slug>-actions/actions/<move-id>/` if it exists.
   Otherwise run `npx -y @neta-art/neta-search-cli@latest skills use neta-search/side-sprite-actions --via find`,
   read it whole and follow it for this character to the end, page built and published (its page is a second Work;
   later moves add to it and keep the same look; never leave a Work card unpublished) with exactly **one** custom
   action, `--id <move-id> --pixel`:
   - spells, punches, throws, breath, palm strikes, poses on the body: `--rig attack`, `--does "<move>: panels 1-3
     <wind-up>, panel 4 <the release toward the right, or the full pose>, panels 5-6 hold it, panels 7-8 back to a
     relaxed stance. Draw only the body and pose: no fire, light, energy, projectile or any effect."` →
     `"release": 4, "recover": 7`.
   - swords, axes, hammers, staffs: `--rig slash`, panels 1-4 raise, panel 5 the chop, 6-7 hold low, 8 recover →
     `"release": 5, "recover": 8`.
3. **The item**: `"body": { "action": "<the action folder it printed>", "release": 4, "recover": 7 }` (optional
   `"height"`: upright height in effect pixels, default 40). Effects drawn on the body (heal, status, auras,
   blink) paint the character's own silhouette: it holds one frame there, `"still"` (default = release; pick the
   frame with the clearest full-body pose).
4. **One page per character**, `works/web/<character-slug>-vfx` (or the page this character already has): add the
   new item to its `page.json` and keep everything else as it is (old items, titles, `lang`), rebuild and publish
   the same Work.
5. In the check image the character must be theirs in every frame, facing the target, feet on the floor. If
   generation fails, build without `body` and say the stock dummy stands in.

## 2. Build, check, publish, hand over

Pick a kebab-case slug (`ls works/webs/ works/web/ 2>/dev/null` first so it is new) and declare the work:

```bash
node /mods/neta/neta work init web works/web/<slug> --title "<work title in the user's language>"
W=<the work folder init printed>     # new worlds normalize it to works/webs/<slug>: use what init printed
```

Every path below is relative to that `$W`. Write `$W/page.json`:

```json
{
  "title": "Ice mage skill effects",
  "subtitle": "Charge, ice lance, frost nova, frozen",
  "lang": "en",
  "items": [
    { "key": "ice-lance", "id": "moves/ice-lance-throw", "title": "Ice lance", "note": "Freezes for a beat on the hit" },
    { "key": "frost-nova", "id": "ice/frost-nova", "title": "Frost nova" },
    { "key": "pink-heal", "id": "holy/heal", "title": "Pink heal", "opts": { "palette": ["#2a0a1c", "#5c1240", "#9c1f6c", "#d63a96", "#f56cb8", "#ff9ed6", "#ffd0ea", "#ffffff"] } }
  ]
}
```

- `title` and `note` on every item, in the user's language: the name, and one line on what you see (the page shows
  it under the stage). `subtitle` on the page: one line about the set or the character; `world`: the world's name.
- `key`: kebab-case, unique (the same effect twice with two palettes needs two keys); it names the downloads.
- `act`: defaults to true for effects with a character act. `false` = the effect alone: no stock character in the
  preview, the GIF or the page (use it to lay the effect over the user's own sprite). Effects drawn on the body
  (status, heals) need the character to read, so keep their default.
- `bg`: preview backdrop `dark | ground | sky | light | black` (default: the effect's own). Downloads stay transparent.

**The stage: a place in this world** (`page.json` `"scene"`). Every effect plays in front of it, pixelated and dimmed
to the effect's grid; without it the stage is a plain night with a brick floor. Once per page (keep it when adding):

1. A place run → that place card's image. A character run → a location card the character's card names (their
   shop, their home, where they fight), else the world's main location. The image is the card's first `media`
   (`world/locations/X.md` + `../media/…` → `world/media/…`).
2. No location card with an image → make one (one image, about 30–60 s):
   `bash <skill-dir>/tools/make-scene.sh $W --place "<the place, one line, from the card or WORLD.md>" --style "<WORLD.md visualStyle>"`
   — it prints the image path (and reuses `$W/scene.*` if it is there). If it fails, go without a scene.
3. `"scene": { "image": "<that path or the https cover URL>", "ground": 0.8 }` — `ground` is where the feet
   stand, as a fraction from the top of the picture (the front edge of the floor; 0.75–0.85 for side views).

**Who takes the hits** (`page.json` `"target"`). A move with a target (`act.target` in its file) hits a straw dummy
unless another character of this world stands there. Once per page (keep it when adding):

1. Pick one: someone the character's card names (rival, friend, foil, sparring partner), else another character
   of this world who fits the tone (a playful hit on a friend in a cosy world). Never the character itself.
2. Reuse `works/web*/<their-slug>-actions/actions/hit/` if it exists. Otherwise follow `side-sprite-actions` for them
   with exactly one known action, `--id hit --pixel`, to the end, page published (one image, about 1 minute; their
   page is another Work).
3. `"target": { "action": "<that hit folder>" }`. It faces the attacker, recoils on every hit, flashes and takes
   the effect's skin (frozen, charred…). `"target": false` on an item keeps the dummy for that one.

Build (5–60 s; it renders every frame):

```bash
node <skill-dir>/tools/build-page.mjs $W/page.json --out $W/dist      # add --lib $W/lab for lab effects
```

**Check before publishing** — pass criterion: the command ends with `OK`, `$W/check/report.json` has `"ok": true`,
and you have opened every `$W/check/<key>.png` and the colors and motion are what was decided in step 0. Warnings
in the report (an ignored option) mean the item does not look as intended: fix `page.json` or use a lab copy, rebuild.
Do not move or delete `$W/check`. The check images are the visual check: do not install browsers or other tools,
and do not start servers, to screenshot the page.

Publish and settle the card in one command:

```bash
node /mods/neta/neta work publish web $W --from $W/dist
```

- `"code":"world_slug_required"` → set one short kebab-case slug from the world's name (`node /mods/neta/neta world slug set <slug>`) and re-run the same publish.
- If it cannot be finished after `init`: `node /mods/neta/neta work fail web $W --error "<reason>"`.

**Hand over**: on its own line, give the Work through the `interaction-components` skill as a link card with target
`{ "type": "work", "workId": "<id from the publish output>" }` (not a file link, not only an image). Then:

- one line per effect: what it is, and the recolor if any;
- the files for their engine: `files/<key>.png` is a transparent grid of frames, `files/<key>.json` is Aseprite-style
  (frame rects and durations; `meta.pixelfx` has fps, loop, columns and the pivot = the effect's anchor in the
  frame), read by the Aseprite importers for Godot and Unity and by Phaser's atlas loader. For hit feel in their
  own game: `meta.pixelfx.act` has `windup` (start their wind-up that long before the effect), `hits[].t` and
  `hits[].freeze` (stop updating everything for `freeze` seconds at `t`), `shake`, `recovery`. Browser games: the
  page's code box.
- `*.act.png` bakes in the character who acts (theirs with `body`, else the stock grey one) and the straw target:
  a storyboard, or with `body` a ready-made attack sheet. Effects drawn on the body (frozen, poisoned, a scan line)
  are drawn on the stock character.

Close following the **next-steps** skill when it is available. Character runs: offer the next moves (the other
questionnaire options, or the card's other techniques), each as "add <move> to <character>'s page".

## 3. Make a new one (when nothing fits)

Work in a lab copy inside the work folder, never in `<skill-dir>`:

```bash
cp -r <skill-dir>/pixelfx $W/lab && cd $W/lab
node tools/new.mjs <category>/<name>        # add --loop for a loop; writes src/fx/<category>/<name>.js
node tools/render.mjs <category>/<name>     # -> records/<category>/<name>/contact.png
node tools/check.mjs <category>/<name>      # must end "0 fail"
```

Then build with `--lib $W/lab`. Publish `dist` only; `lab` stays in the world as the source.

How to make it good — read `pixelfx/UPSTREAM-SKILL.md` section "3. Make a new one" (the method, and a "you see →
fix" table) and `pixelfx/docs/AUTHORING.md` (the effect contract, toolkit, painter API, acts) before drafting. In
short: say it in one line with art direction; read the two or three closest existing effects and borrow their
techniques; when the direction is open, draft 2–3 genuinely different versions and render them all; look, judge like
a picky pixel artist, fix the worst thing, render again — **three rounds minimum**; give anything with a character an
act (wind-up, release pose, freeze on contact, recovery) and judge motion with `tools/act.mjs`; finish with
`check.mjs` passing. Delete the drafts you didn't keep. Never use `Math.random` (seeded helpers only), and never
copy art from a commercial game (its sprites, logos, UI). The user's own characters and this world's characters
are fine — section 1b is how they appear.

## 4. Gotchas

- Keep the credit: the page footer and `pixelfx/LICENSE` + `NOTICE.md` ship with every page; do not remove them.
  The upstream gallery font is not MIT and is not bundled — do not fetch or use it.
- More effects for the same game or character → add items to the same `page.json`, rebuild, publish the same work.
- Full-screen effects (`explosions/nuke`, `explosions/big-explosion`, weather) cost 4–5 ms a frame in a browser:
  say so if the user plans many at once.
- Do not claim an effect matches a character's colors without having opened its check image.
- `act.mjs --sheet` ignores `--out`; the page build already makes the act sheets.
- `render.mjs` takes options only as `--opts '<json>'`; an unknown flag like `--palette` is silently ignored.
- Run `build-page.mjs` by its absolute path (`<skill-dir>/tools/build-page.mjs`) from the world root, and pass the
  work folder to `work publish` relative to the world root (`works/web/<slug>`), not `.` and not an absolute path.
- Image generation can refuse a well-known character's name (`PROHIBITED_CONTENT`) or time out: retry once, then
  describe the look in `--who` without the name (costume, colours, build). Report it in one line.
- In the reply, link the Work card only; do not link `/workspace/...` file paths (the user cannot open them).

## Out of scope

- Do not change world settings (the slug only when publish asks for one, as above).
- Do not delete files that existed before this run; do not edit memory, character cards, installed scripts,
  existing Works other than this skill's own page, or roleplays.
- Do not build a game or walk cycles; one character action per move (1b), one move per character run; do not act
  on your own next-step suggestions.
- Do not install global packages or tools (`npm i -g`, browsers); everything needed is Node and this folder.
- Do not edit files in `<skill-dir>`; changes go in a lab copy.