Time is an argument, so speed scales it and a prewarm offsets it (#87)
game-maker / suite (push) Successful in 9m48s

Speed and Prewarm are not state and not a second loop: both are arithmetic
on the clock argument the field already passes to every particle formula.
fieldTime = elapsed * timeScale + prewarmOffset, a pure rule next to
liveRange, called at the one place ParticleField.sync forms its time, so
preview and world inherit it together.

Prewarm offsets by one lifetime because that is the smallest offset which
fills a continuous emitter; a burst is dead at time >= lifetime, so the
same offset would skip it entirely and it is suppressed there.

The tab's slider counts wall-clock seconds, so its span divides by the
scale. A missing row falls back to 1 / off, so old project files need no
migration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Opus 5 committed 2026-09-14 07:31:07 +02:00
1 parent fbb2d157f0
commit 8ae20d044f
8 files changed
+191 -10

No files matched your search

+4
View File
@@ -35,7 +35,9 @@ import {
PARTICLE_SIZE_KEY,
PARTICLE_TEXTURE_KEY,
particleParamDefs,
PREWARM_KEY,
RATE_KEY,
TIME_SCALE_KEY,
} from './particles';
import { SHADER_KEY, shaderOf, shaderParamDefs } from './shaders';
@@ -220,6 +222,8 @@ const ASSET_SCHEMAS: Record<AssetType, PropertySchema> = {
{ key: RATE_KEY, label: 'Rate', kind: 'number', default: 20, min: 0, step: 1 },
{ key: BURST_COUNT_KEY, label: 'Burst count', kind: 'number', default: 20, min: 0, step: 1, decimals: 0 },
{ key: LIFETIME_KEY, label: 'Lifetime', kind: 'number', default: 1, min: 0.01, step: 0.1 },
{ key: TIME_SCALE_KEY, label: 'Time scale', kind: 'number', default: 1, min: 0, step: 0.1 },
{ key: PREWARM_KEY, label: 'Prewarm', kind: 'boolean', default: false },
{
key: MAX_PARTICLES_KEY,
label: 'Max particles',
+4
View File
@@ -15,6 +15,8 @@ export const MODE_KEY = 'mode';
export const RATE_KEY = 'rate';
export const BURST_COUNT_KEY = 'count';
export const LIFETIME_KEY = 'lifetime';
export const TIME_SCALE_KEY = 'timeScale';
export const PREWARM_KEY = 'prewarm';
export const MAX_PARTICLES_KEY = 'maxParticles';
export const PARTICLE_SIZE_KEY = 'size';
export const PARTICLE_TEXTURE_KEY = 'texture';
@@ -54,6 +56,8 @@ const RESERVED_KEYS: ReadonlySet<string> = new Set([
RATE_KEY,
BURST_COUNT_KEY,
LIFETIME_KEY,
TIME_SCALE_KEY,
PREWARM_KEY,
MAX_PARTICLES_KEY,
PARTICLE_SIZE_KEY,
PARTICLE_TEXTURE_KEY,