In order to make a pixel VFX art, just typing it in your terminal
> Make a 32 px poison cloud that lingers
…then Claude builds the effect, checks it and corrects it. One effect typically takes 20–45 minutes. The result is a game-ready sprite sheet with frame timings and hit events, for Godot, Unity or GameMaker. Claude made every effect in the GIF above from a JSON file. Nobody painted or edited a pixel by hand.
This is spritefx, an open-source (MIT) pixel-art VFX engine that ships as a Claude Code skill.
Install it in one command
git clone https://github.com/HoangLong256/spritefx ~/.claude/skills/spritefx
Then ask for effects in any project, in your own words:
> A slash, hit and trail set for my greatsword
> A blue portal: opening, idle loop and closing
> Give my healing potion a sparkle effect, 48 px
On first use Claude sets up the skill's Python environment (Python 3.11+ is the only requirement).
Claude doesn't draw pixels. That's the point.
Image models can make images that look like pixel art at a glance. For game VFX, their output usually has off-grid pixels, too many colours and soft edges. Their frames often do not animate together. So spritefx divides the work:
- Claude writes a JSON spec. The spec describes the effect as phases and layers. Examples are a dark contrast frame, a white flash, a noise fireball, a shock ring and smoke puffs.
- The engine draws it. A deterministic Python renderer simulates each layer tick by tick. It changes each value to a palette colour. The same spec always gives byte-identical PNG files.
- 22 pixel-art checks grade the result. Does the flash occur before the peak? Does the smoke last longer than the fire? Do pixels flicker A-B-A? Is the effect visible on a light background? One fault stops the build.
- Claude reads the faults and the review sheets, then corrects the spec. Claude never edits the pixels. The loop continues until the build passes.
This loop is the key. An AI cannot measure "make it look good". It can measure "smoke_tail: smoke ends before the fire", and it can correct that fault.
Why pixel-art rules, and why check them?
As an indie dev, I find effects painful to make, and most AI image models cannot generate effects that stay consistent from frame to frame. Procedural effects usually show four defects: soft alpha edges, noisy blobs, too many colours, and smoke that fades instead of breaking into pieces.
Pixel artists avoid these defects on purpose. A good hand-drawn explosion follows a known recipe:
- a dark contrast frame,
- a one-frame white flash,
- a hot core with a cool rim,
- smoke that erodes into dots.
Left: the raw values of the simulation, drawn the usual way with soft alpha and blur. Right: the same frames after spritefx.
Smoke is the clearest example. The smoke does not fade to transparent. It erodes: blob, then crescent, then dots, then nothing. Each pixel stays fully opaque at all times. So the smoke stays readable at 1× size.
What Claude writes: the spec
Here is a complete hit spark. Claude writes specs like this for you, or you can write them by hand. The effect is a 4-point star that flares and then erodes, with radial streaks.
{
"name": "hit_spark", "type": "hit", "canvas": "auto", "anchor": "center", "fps": 30, "seed": 3,
"ramps": {"spark": {"colors": ["#9e2835", "#f77622", "#feae34", "#fee761", "#ffffff"]}},
"phases": [
{"name": "flash", "ticks": 2, "fast": true, "events": ["hit"]},
{"name": "burst", "ticks": 3},
{"name": "fade", "ticks": 5}
],
"layers": [
{"id": "star", "kind": "shape", "ramp": "spark",
"shape": {"sdf": "star", "points": 4, "r": {"keys": [[0, 7], [0.2, 9], [1, 3]], "ease": "out"}, "inner": 0.3},
"value_mode": "radial", "edge": 0.0, "break_up": {"after": 0.45, "noise": "angular"}},
{"id": "streaks", "kind": "particles", "ramp": "spark", "tag": "debris",
"emit": {"mode": "burst", "count": [6, 7]}, "velocity": {"speed": [1.6, 2.6], "angle": "out"},
"drag": 0.18, "life": [6, 9], "stamp": {"kind": "streak", "size": {"keys": [[0, 3], [1, 1]]}}}
]
}
A few ideas carry the whole design:
-
Phases run on a 30 fps tick clock. You write
flash → burst → fade, not "frame 1, frame 2…". -
Parameters use keys and easing. The radius of the star increases from 7 to 9 px. Then it decreases to 3 px with an
outease. The radius does not change linearly. - You select a colour ramp, never a colour per pixel. Each layer maps its value to a ramp from dark to light. So each pixel is a palette colour, and no pixel has soft alpha.
The engine has ten layer kinds. They include SDF shapes, particles, loopable noise fields, lightning bolts, Doom-style cellular fire, a grid smoke simulation and a FLIP water solver. At the end, the engine changes the output of each layer to palette colours.
One spec, many looks
Claude selects colour ramps, not colours. So a new colour scheme for an effect is a small change. These four explosions use the same spec. Only its two ramps (blast and soot) are different. Timing, shapes and smoke are the same, and all four pass every check.
So a request like "make ice, poison and arcane versions of my explosion" needs little work. The motion stays the same, and only the palette changes.
The checks that keep Claude honest
Pixels are the easy half. The hard half is to know when an effect is wrong. So each build runs 22 craft checks. fx build writes the sheets only when all of them pass. Some examples:
| Check | What it enforces |
|---|---|
envelope |
Fast rise, slow decay. Coverage peaks early, and the decay lasts at least 1.5× the rise |
flash_order |
The brightest frame occurs first, before the effect grows |
smoke_tail |
Smoke lasts longer than fire |
flicker |
No pixel blinks A-B-A across frames |
orphans |
No single stray pixels, except pixels that you tag as sparks |
colors |
At most 12 colours per sheet and 6 per layer |
seam |
A loop has no jump where it starts again |
residue |
The last frame of a one-shot is empty |
Each build also writes an envelope chart. It shows coverage, lightness and colour use over time, with shaded phases.
One rule keeps the project honest. Correct a failed check in the spec. Never edit the pixels, and never loosen the limit.
Calibration against hand-drawn effects by pixel artists set four of the limits. The other limits are first proposals, and tuning continues. Also, a pass is necessary but not sufficient. Some effects pass every check and still look weaker than hand-drawn work. So I also examine each effect by eye.
Output for your game engine
A build gives you:
- a one-row sprite strip with cells of equal size,
- an Aseprite-style JSON with frame durations, phase tags, events and the anchor,
- a base sheet and an additive sheet, for glow with additive blending,
- an emissive sheet for bloom or lights,
- an 8-bit indexed PNG for palette swaps.
The documentation shows how to connect the sheets in Godot, Unity and GameMaker.
Demo: the witch summons a devil… and gets a bunny
This 12-second scene uses only generated sheets. spritefx specs make all its effects: the demonic circle, the staff charge, the smoke column, the burst, the reveal pop and the hearts.
Prefer to skip the AI?
The engine also operates without Claude. It needs no GPU and no game engine. It needs only Python 3.11 and three dependencies (numpy, Pillow, jsonschema):
git clone https://github.com/HoangLong256/spritefx && cd spritefx
python3.11 -m venv .venv && .venv/bin/pip install -e ".[test]"
.venv/bin/python -m fx build examples/explosion.json --out out
👉 github.com/HoangLong256/spritefx
New effect specs are the most useful contribution. Add one to examples/ that builds with zero faults.
Please tell me two things in the comments:
- Which effect do you want next?
- Which craft rule does the audit not check yet?








Top comments (0)