P17.2: organic fall — per-column stagger (cascade pour)
render_fall now offsets each COLUMN's drop START by a small bounded delay (fall_stagger_t) so a refilled/collapsed row pours in as a left-to-right cascade instead of every gem snapping down in one flat lockstep row. Column col waits FALL_STAGGER_MAX (0.30) * col/7 of the fall window, then falls over the remaining 1 - 0.30, with that local progress fed through ease_in_cubic so each column still accelerates under gravity within its own window. Bounded by construction: the last column lands EXACTLY at t=1 and every earlier column strictly before it, so no gem is ever left mid-air at the segment end — the seam to the next round / settled board stays invisible and move.final is untouched. FALL_ANIM_DUR (0.22s) and the timeline helpers (phase/total/cascade_rounds_started) are unchanged, so the per-round cascade-cue timing snapshots don't churn and live per-round audio is unaffected. Render-only — no board.sx model change. tests/easing.sx pins fall_stagger_t: f(0)=0, f(1)=1 across all columns (no gem unlanded), per-column monotonicity, and the mid-fall cascade ordering (each later column strictly behind the one before). tests/anim_plan.sx (final==model, contiguity) stays green. Golden goldens/p17_stagger.png: M3TE_FX=11 (depth-5 cascade, seed 1337) pinned at M3TE_ANIM_TIME=1.91 — round 4 refills columns 2-7 by one cell each, so the top row reads as a left-to-right staircase (vs the pre-stagger flat row in p17_fall.png).
This commit is contained in:
@@ -141,6 +141,41 @@ main :: () -> s32 {
|
||||
if !bb_overshoot_bounded { fails += 1; }
|
||||
if !bb_settles { fails += 1; }
|
||||
|
||||
// 6. Per-column fall stagger (P17.2): the fall window offsets each column's drop
|
||||
// START by a BOUNDED delay so a refilled row pours in as a cascade, yet EVERY
|
||||
// column still lands EXACTLY on its cell by the segment end. Lock: at t==0 no
|
||||
// column has moved; at t==1 EVERY column has reached local progress 1 (no gem
|
||||
// left mid-air — the seam to the next round stays invisible); per-column local
|
||||
// progress is monotonic in t; and MID-fall the columns form a cascade — each
|
||||
// later column has made STRICTLY LESS progress than the one before (its drop
|
||||
// starts later), the opposite of a flat lockstep row sharing one progress.
|
||||
print("== fall stagger bounded ==\n");
|
||||
stg_t0 := true; stg_t1 := true;
|
||||
for 0..BOARD_COLS: (c) {
|
||||
if fall_stagger_t(0.0, c) != 0.0 { stg_t0 = false; }
|
||||
if fall_stagger_t(1.0, c) != 1.0 { stg_t1 = false; }
|
||||
}
|
||||
stg_cascade := true;
|
||||
for 1..BOARD_COLS: (c) {
|
||||
if !(fall_stagger_t(0.5, c) < fall_stagger_t(0.5, c - 1)) { stg_cascade = false; }
|
||||
}
|
||||
stg_mono := true;
|
||||
for 0..BOARD_COLS: (c) {
|
||||
pp := fall_stagger_t(0.0, c);
|
||||
for 1..21: (i) {
|
||||
tt := cast(f32) i / 20.0;
|
||||
vv := fall_stagger_t(tt, c);
|
||||
if vv < pp - 0.000001 { stg_mono = false; }
|
||||
pp = vv;
|
||||
}
|
||||
}
|
||||
print("stagger_t0 {} stagger_t1 {} stagger_cascade {} stagger_mono {}\n",
|
||||
stg_t0, stg_t1, stg_cascade, stg_mono);
|
||||
if !stg_t0 { fails += 1; }
|
||||
if !stg_t1 { fails += 1; }
|
||||
if !stg_cascade { fails += 1; }
|
||||
if !stg_mono { fails += 1; }
|
||||
|
||||
if fails == 0 {
|
||||
print("ok: easing toolkit endpoints locked + amplitudes bounded\n");
|
||||
return 0;
|
||||
|
||||
@@ -8,4 +8,6 @@ back_overshoots true back_bounded true spring_overshoots true spring_bounded tru
|
||||
squash_moves true squash_two_sided true squash_bounded true
|
||||
== illegal-swap bounce ==
|
||||
bounce_ends true peak_amp true peak_loc true overshoots true overshoot_bounded true settles true
|
||||
== fall stagger bounded ==
|
||||
stagger_t0 true stagger_t1 true stagger_cascade true stagger_mono true
|
||||
ok: easing toolkit endpoints locked + amplitudes bounded
|
||||
|
||||
Reference in New Issue
Block a user