From 198483b1550926be98e6c738c6efb0712e3afa3f Mon Sep 17 00:00:00 2001 From: root Date: Mon, 14 Sep 2026 07:31:14 +0200 Subject: [PATCH] Speed and Prewarm are arithmetic on the clock, not a second loop (#87) Co-Authored-By: Claude Opus 5 --- Architecture.md | 5 ++++- Development.md | 4 ++-- Particles.md | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Architecture.md b/Architecture.md index 29410ef..f0d4ba0 100644 --- a/Architecture.md +++ b/Architecture.md @@ -105,7 +105,10 @@ of 500 particles is reproducible, holds still for a check, and needs no state be source stood when each one was born. Both are pure and tested without a browser. The other side of that choice: **freezing such a thing means moving its origin, not pausing a counter** — the clock belongs to the library and keeps running, so a preview let go after a minute on hold has to be -rebased to the second it was stopped at, or it resumes a minute further on. +rebased to the second it was stopped at, or it resumes a minute further on. The good side: a row +that changes *when* rather than *what* costs nothing but a term on that one argument — a particle +source's `Time scale` is a factor on it and `Prewarm` a summand, so neither needs a frame of +simulation nor a line in the drawing code. Comments state contracts and reasons, not what the code does: a `/** */` on every export whose name does not say it all, `//` only for a decision or gotcha. diff --git a/Development.md b/Development.md index 163fb04..7b2c84e 100644 --- a/Development.md +++ b/Development.md @@ -12,7 +12,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs # code is lost (tail's is reported), so a red run reads as green npm run build # writes dist/ and regenerates index.html ./build.sh # the same under `set -o pipefail`, for callers that pipe the output -node tools/seed-e2e.mjs && node tools/e2e.mjs # 816 editor checks, screenshots in /tmp/gm-e2e-*.png +node tools/seed-e2e.mjs && node tools/e2e.mjs # 821 editor checks, screenshots in /tmp/gm-e2e-*.png GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step ./e2e.sh start [GM_STEPS] # the same run detached, see below ./e2e.sh status # live progress, or the last run's result @@ -156,4 +156,4 @@ widths to find click points. The **render device is not in this repo** — `/dev and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`, -WebGL 2.0, and the same 816 checks as here. +WebGL 2.0, and the same 821 checks as here. diff --git a/Particles.md b/Particles.md index f8449a6..71c53f6 100644 --- a/Particles.md +++ b/Particles.md @@ -27,7 +27,8 @@ nothing. Right of it, past a divider that drags, the **preview** panel emits the asset's own particles from its middle, wearing **the rows the asset itself carries** — edit `Rate` or `Lifetime` on the asset -and the panel changes with them, including how far the slider reaches (three lifetimes). Rows the +and the panel changes with them, including how far the slider reaches (three lifetimes, which a +`Time scale` of 2 covers in half the seconds). Rows the asset leaves alone fall back to the type's defaults: 20 a second, one second each, a plain 16 px square. It stands beside the graph rather than under it because a graph is read across: width is what it can spare, height is not. `Hold` stops the clock where it is and turns into `Run`; the @@ -78,6 +79,8 @@ mirror), so hanging one on a moving ship turns the whole spray with it. Its own | **Rate** | 20 | Particles per second, for a continuous source. | | **Burst count** | 20 | How many go out per burst. | | **Lifetime** | 1 s | How long one particle lives — **the scale that gives `Age` its meaning**. | +| **Time scale** | 1 | How fast the source's own clock runs: 2 is twice the speed, so it emits twice as often and a particle is gone in half the time. Every row above is read on that clock, which is why none of them has to be touched to slow a whole effect down. 0 holds the picture where it is. | +| **Prewarm** | off | Start one lifetime in, which is the second a stream first stands full. Without it a fire lit by a scene fade-in begins as a single spark and takes a lifetime to look like a fire. Nothing to a *Burst*, whose particles are all gone by that second. | | **Max particles** | 500 | The most alive at once; past it the oldest are dropped. | | **Size** | 16 | The particle's size in pixels, which the graph's `scaleX`/`scaleY` multiply. | | **Texture** | none | The picture each particle is drawn with. Without one it is a plain square. |