Skip to content

feat: collide the layers, give each layer its own motion, and stretch Ripple - #13

Merged
simien merged 1 commit into
mainfrom
feat/collide-layer-motion
Sep 14, 2026
Merged

simien merged 1 commit into
mainfrom
feat/collide-layer-motion

Conversation

@simien

@simien simien commented Sep 14, 2026

Copy link
Copy Markdown
Owner

What changes

Collide, a slider under Direction in the Animation section. The two layers push on each other under whatever motion is running: each layer's field is bent along the ridges of the other layer's field as it is that frame, so under Loop, Drift, and Wind the two flows bend each other as they move. It rises and settles once per cycle like Tide, so the still is untouched and every cycle closes. The pusher's field is sampled on a two-cell lattice because under a moving motion it is rebuilt every frame; a Loop frame with Collide costs 52ms against Loop's 39ms at 1200 by 630. Tide is now Collide at full with nothing else moving.

Motion per layer. Each layer tab has a Motion menu that follows General unless changed, so one layer can loop while the other pulses or holds still, all on the one Speed. Choosing a Motion on the General tab puts both layers back to Same, and a layer's menu names the layer in its toast. If General is None and a layer runs its own kind, the preview plays and the Speed controls appear.

Ripple stretches instead of stepping. The motion no longer touches the grid builder. The swell grows and shrinks each finished layer's shapes along the rings, and the pull moved into the painter, which reads every pixel from the cell under the refracted point at pixel resolution, so block edges slide and blocks stretch. generate() returns warp alongside the grids and renderToCanvas reads it; every render call site passes it through. Drops fall on the canvas as a whole, and in the live preview each lands somewhere new every life via loopCycle; exports leave it out so their rain repeats and the loop closes.

Wind and Loop read as different things. Wind's broad mass holds still while the gust bends it and the fine octaves stream through; it used to slide like Drift with the gust on top. Layer B circles the other way under Loop and in Wind's gust, so the layers sway against each other. Layer A under Loop is bit-identical to before.

Examples. The three reroll clips are removed. The six motion clips are re-rendered from six distinct compositions, kaleidoscope on Loop only, with captions to match.

Links. Collide and both layers' motions are tail fields whose zero means off and Same, so every existing link opens as it did. Links grow from 83 to 84 characters.

Verification

  • With Collide off and both layers on Same, every existing motion renders bit-identical to the old generator; stills, Drift, and Pulse are bit-identical after the Wind and spin changes too.
  • Collide closes exactly and opens on the still under every kind. Ripple, Wind, and Loop close exactly.
  • A layer set to None holds still while the other moves; a reversed frame at phase p still equals the forward frame at 1 - p.
  • Links round-trip Collide and per-layer motion in the app.
  • checks.py origin/main passes, including the cache bust (generator.js 13 to 14) and the link-format comparison.
  • Guide, explainer, README, and CLAUDE.md are updated.

🤖 Generated with Claude Code

… Ripple

Collide, under Direction in the Animation section, makes the two
layers push on each other under whatever motion is running: each
layer's field is bent along the ridges of the other layer's field as
it is that frame, so under Loop, Drift, and Wind the two flows bend
each other as they move. It rises and settles once per cycle like
Tide, so the still is untouched and every cycle closes. The pusher's
field is sampled on a two-cell lattice, since under a moving motion it
is rebuilt every frame. Tide is now Collide at full with nothing else
moving, and reads the same lattice.

Each layer tab has a Motion of its own that follows General unless
changed, so one layer can loop while the other pulses or holds still.
Choosing a Motion on General puts both layers back to Same, and a
layer's own menu names the layer in its toast. If General is None and
a layer runs a kind, the preview plays and the Speed controls show.

Ripple no longer touches the grid builder. The swell grows and shrinks
each finished layer's shapes along the rings, and the pull moved into
the painter, which reads every pixel from the cell under the refracted
point, so blocks stretch as a ring passes rather than stepping a cell
at a time. Drops fall on the canvas as a whole, and in the live preview
each lands somewhere new every life; exports repeat their rain so the
loop closes.

Wind's broad mass now holds still while the gust bends it and the fine
octaves stream through; it used to slide like Drift with the gust on
top. Layer B circles the other way under Loop and in Wind's gust, so
the layers sway against each other rather than as one.

The three reroll example clips are removed, and the six motion clips
are re-rendered from six distinct compositions, kaleidoscope on Loop
only. Collide and the layers' motions travel in links as tail fields
whose zero is off and Same; links grow from 83 to 84 characters.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 14, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
flield b759604 Commit Preview URL

Branch Preview URL
Sep 14 2026, 02:59 AM

@simien
simien merged commit b659733 into main Sep 14, 2026
2 checks passed
@simien
simien deleted the feat/collide-layer-motion branch September 14, 2026 03:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant