Written with AI help (Claude), checked against the project's docs. Pixelbolt is made by our small lab, so we're not neutral; every number below comes from a run on 3 November 2026 with Pixelbolt 0.11.0 from npm.
This is a looping pixel art waterfall for a 2D game: water leaves a mossy stone ledge in an arc, lands in a basin and spills over its lip. It's made with Pixelbolt, an MIT-licensed tool that simulates the water as particles on a pixel grid and bakes each frame into palette pixels.
What you get

The waterfall preset, unchanged, rendered by pixelbolt gif at 6× on a dark background.
- 48 × 64 pixels, 24 frames of 60 ms (a 1.44 s loop at 16.67 fps)
- 9 palette colours on a transparent background (the GIF above is blended onto a dark colour and enlarged 6×)
- a 384 × 192 sprite sheet (8 × 3 cells), a TexturePacker-style atlas JSON with each frame's rectangle and duration, a GIF, an animated PNG and single frames
The browser way
The guide gives four steps:
- Open the waterfall in the playground from the guide's waterfall section (link at the end). The link carries the whole recipe, with nothing to install and no account.
- Change a value in the Recipe JSON box. The preview renders again after each edit.
- Choose a scale from 1× to 16× for the frame PNG and the GIF. The sheet and atlas stay at the art's own size.
- Download the sheet, the atlas PNG and JSON, the GIF, a frame PNG or the recipe. Copy link makes a link to your edited version.
A note on versions: the guide's link and commands name Pixelbolt 0.9.1. The commands below use 0.11.0, the newest release. The recipe, size and timing are the same, but 0.11.0's liquid changes alter about 150 to 220 of each frame's 3,072 pixels. Its changelog says the waterfall's foot "splits into strands a little more".
The command-line way
You need Node.js 20 or newer. The waterfall ships as a preset:
npx -y pixelbolt@0.11.0 compile --preset waterfall --out waterfall.json
npx -y pixelbolt@0.11.0 gif waterfall.json --scale 6 --background "#17191d" --out waterfall.gif
npx -y pixelbolt@0.11.0 render waterfall.json --out waterfall
compile runs the simulation and writes an ordinary recipe of frames. gif enlarges it by a whole number and blends it onto one colour. render writes a folder holding the sheet, the atlas JSON, the frames, an animated PNG, CSS, a canvas player and a preview page. It also writes waterfall.tres, which the folder's README.txt calls a Godot 4 SpriteFrames file; we haven't tested that file. For engines in general, the guide says to slice the sheet as a grid of equal cells. Nothing is overwritten unless you add --force.
One knob, changed
The guide names the settings under effects → waterfall:
-
velocityon thesourceemitter ([1.1, 0]), which sets how far out the arc reaches -
pulse, which surges the flow four times a loop -
whitewaterfor spray and foam -
flip, livelier toward 1 and calmer toward 0 - the
depthcolour layer
To edit the recipe, save it as waterfall.fluid.json with the playground's Recipe JSON button, or download the same file from the npm package (in Windows PowerShell, type curl.exe):
curl -O https://cdn.jsdelivr.net/npm/pixelbolt@0.11.0/examples/waterfall.fluid.json
Compiling that file gives byte-for-byte the same result as the preset. We changed velocity from [1.1, 0] to [1.6, 0] and nothing else:
npx -y pixelbolt@0.11.0 compile waterfall.fluid.json --out waterfall-fast.json
npx -y pixelbolt@0.11.0 gif waterfall-fast.json --scale 6 --background "#17191d" --out waterfall-fast.gif

The same recipe with velocity at [1.6, 0].
The arc now lands near the basin's right lip instead of mid-basin. Halfway down (row 30), the stream's centre moved from x 24–27 to x 29.5–30. More water reaches the basin: the pool's surface rose from rows 43–45 to row 39, more spills over the lip, and the drawn water went from 619–640 to 708–739 pixels a frame. Size, timing and loop didn't change.
Not every value is accepted. A pulse period of 5 is refused: "a looping effect repeats every 24 frames, so the period must divide 24".
Numbers from our run
Node 24.19.0, Windows 11, a 16-core desktop CPU:
-
compiletook 3.02, 3.32 and 3.27 s through npx, which needs about 2.3 s just to start. Run with node on the same package, it took 1.03–1.07 s, about 0.3 s of that Node's start-up. -
gifandrendereach took about 0.35 s with node. - Every run gave byte-identical files.
- The GIF is 288 × 384 pixels and 41,809 bytes, the sheet 6,519 bytes and the atlas 9,599 bytes.
How it works
Pixelbolt's physics notes describe one grid per effect, one cell per pixel, with the liquid carried by particles, four to a full cell. Each step moves the particles' motion onto the grid, applies gravity and cohesion, and solves for pressure. It then hands the velocities back to the particles and moves them, never into a solid. The maths uses only basic arithmetic, square roots, the project's own trigonometry and seeded hashing, with fixed step counts, so a recipe gives the same pixels on every run. The stated aim is the picture: "When accuracy and looks disagree, looks win."
Limits
- A fluid canvas is at most 128 × 128 pixels, with up to 16 emitters and 32 obstacles per effect.
- One liquid per effect: mixing several is "out of scope for now".
- Frames are at most 256 × 256 pixels, and a project holds at most 256 frames.
- It imports PNG only, doesn't edit GIF or Aseprite files, uses no image model and isn't meant for painted or photographic art.
- Spray and foam are still drawn as single pixels and dashes.
- It's tuned for looks, not engineering accuracy.
Links
- The water guide's waterfall section: https://skulitom.github.io/Pixelbolt/guides/pixel-art-water-animation/#waterfall
- The fluid physics model: https://github.com/skulitom/Pixelbolt/blob/main/docs/physics-model.md
Top comments (0)