P18.2: organic combine — staggered clear ripple (sx, iOS sim)
Within a clearing round the matched gems no longer all explode at once: each gem's pop (and its burst) START is offset by a bounded per-gem delay so the cells detonate as a ripple. - board_anim.sx: clear_ripple_t(t,u) mirrors fall_stagger_t's (t-delay)/window, delaying a gem's pop START by CLEAR_STAGGER_MAX*u (0.45 of the clear window). Bounded: every gem still reaches local 1 (scale 0) by t==1, so none is left mid-pop at the seam to the fall. clear_diag_span/clear_rank rank each matched gem 0..1 by diagonal (col+row) PER ROUND, so even a 3-match ripples across the full budget. - board_view.sx render_clear: feed each matched gem's ranked, staggered local t through the P18.1 clear_pop_scale (locked endpoints unchanged). - board_fx.sx: bursts carry the same per-gem delay so they ripple in lockstep with the pops. Per-round audio cue (P10.10) still fires once at t0, not per gem. - Model untouched (same cells cleared, same final board); CLEAR_ANIM_DUR fixed, so cascade-cue snapshots don't churn and M3TE_ANIM_TIME=0 still rests. - tests/easing.sx: pin clear_ripple_t endpoints, bounded completion by t==1, monotonicity, ripple ordering, and the diagonal rank. - goldens: add p18_stagger (M3TE_FX=3 @ 0.22); refresh p18_pop, p6_fx_match, p11_combo_deep (all pinned mid-clear, now showing the ripple).
This commit is contained in:
@@ -136,6 +136,52 @@ round_land_time :: (k: s64, col: s64) -> f32 {
|
||||
+ fall_landing_frac(col) * FALL_ANIM_DUR
|
||||
}
|
||||
|
||||
// Per-gem clear ripple (P18.2): within a clearing round the matched gems pop as a
|
||||
// RIPPLE, not all at once. Each gem gets a normalized rank `u` in [0,1] (its
|
||||
// diagonal position within the round's matched cells, lowest-diagonal = 0), and
|
||||
// this offsets that gem's pop START by a BOUNDED delay so rank 0 pops first and
|
||||
// rank 1 last, yet EVERY gem still reaches local 1 (clear_pop_scale → scale 0,
|
||||
// fully cleared) by the clear segment's end — no gem is left mid-pop at the seam
|
||||
// to the fall. Returns the gem's LOCAL 0..1 progress, fed through clear_pop_scale
|
||||
// (whose locked endpoints keep the seam to the model board). Mirrors
|
||||
// fall_stagger_t's (t-delay)/window. `tests/easing.sx` pins f(0,.)/f(1,.), the
|
||||
// bounded completion by t==1, monotonicity, and the rank ordering.
|
||||
CLEAR_STAGGER_MAX :f32: 0.45;
|
||||
clear_ripple_t :: (t: f32, u: f32) -> f32 {
|
||||
delay := CLEAR_STAGGER_MAX * u;
|
||||
window := 1.0 - CLEAR_STAGGER_MAX;
|
||||
lt := (t - delay) / window;
|
||||
if lt <= 0.0 { return 0.0; }
|
||||
if lt >= 1.0 { return 1.0; }
|
||||
lt
|
||||
}
|
||||
|
||||
// The diagonal (col+row) extent of a round's matched cells — the span the ripple
|
||||
// ranks each matched gem across. `hi < lo` only if the mask is empty.
|
||||
ClearDiag :: struct { lo: s64; hi: s64; }
|
||||
clear_diag_span :: (m: *MatchMask) -> ClearDiag {
|
||||
lo : s64 = (BOARD_COLS - 1) + (BOARD_ROWS - 1) + 1;
|
||||
hi : s64 = -1;
|
||||
for 0..BOARD_CELLS: (i) {
|
||||
if m.cells[i] {
|
||||
d := (i % BOARD_COLS) + (i / BOARD_COLS);
|
||||
if d < lo { lo = d; }
|
||||
if d > hi { hi = d; }
|
||||
}
|
||||
}
|
||||
ClearDiag.{ lo = lo, hi = hi }
|
||||
}
|
||||
|
||||
// Normalized rank (0..1) of cell (col,row) within a round's matched diagonal span
|
||||
// — 0 for the earliest-popping (lowest-diagonal) gem, 1 for the last. Normalizing
|
||||
// PER ROUND (not across the board) lets even a small 3-match ripple across the
|
||||
// full stagger budget. A degenerate span (every matched cell on one diagonal)
|
||||
// ranks all gems 0, so they pop together rather than dividing by zero.
|
||||
clear_rank :: (span: ClearDiag, col: s64, row: s64) -> f32 {
|
||||
if span.hi <= span.lo { return 0.0; }
|
||||
cast(f32) ((col + row) - span.lo) / cast(f32) (span.hi - span.lo)
|
||||
}
|
||||
|
||||
// One recorded cascade round. `before` is the board at the round's start (the
|
||||
// swapped board for round 0, the previous round's `after` otherwise — never has
|
||||
// holes). `matched` flags the cells cleared this round (they scale out). `src`
|
||||
|
||||
Reference in New Issue
Block a user