P17.3: organic fall — per-round landing squash-&-settle (sx, iOS sim)
Give each landing gem a wide-and-short squash-&-settle bounce as it touches its destination, applied WITHIN the fall so EVERY cascade round bounces (staggered per column), not only the final whole-move settle. One envelope, one bounce: land_squash is now LAND_SQUASH_A * squash_envelope (P15.1) over its normalized window, so the per-round fall bounce and the settle bounce are the exact same shape. render_fall/render_clear age a per-column bounce from each column's touch-down instant (fall_landing_frac * FALL_ANIM_DUR) via the shared rest_squash + delivering_round helpers, so a gem still in the air draws unsquashed and only a landed gem flattens; the squash carries across the fall->clear seam. Double-bounce reconciliation (approach a): drive the bounce from the per-round fall and DROP the old whole-move "stamp at age 0" settle. The settle stamp is now BACK-DATED per column (clock - (total - round_land_time)) so render_gems resumes land_squash exactly where render_fall left off at the render_anim -> render_gems seam — one continuous bounce, no double-pop. Amplitude tuned 0.13 -> 0.18 (~13% peak) so the bounce reads while staying tasteful; durations unchanged, so the cascade-cue snapshots don't churn. M3TE_ANIM_TIME=0 still reproduces goldens/p6_idle_t0.png (a resting board carries no landing stamp). New goldens/p17_land.png pins a staggered landing mid-pour (M3TE_FX=11 ANIM_TIME=1.94). tests/easing.sx gains a landing-instant section pinning fall_landing_frac / round_land_time; tests/gem_pose.sx stays green (land_squash values are identical).
This commit is contained in:
20
gem_anim.sx
20
gem_anim.sx
@@ -12,6 +12,7 @@
|
||||
#import "modules/std.sx";
|
||||
#import "modules/math";
|
||||
#import "board.sx";
|
||||
#import "board_anim.sx";
|
||||
|
||||
// A gem's draw transform about its cell centre. scale_x/scale_y scale the sprite
|
||||
// (1.0 == the normal cell-fill size) and dx/dy nudge it in CELL units. The resting
|
||||
@@ -63,14 +64,15 @@ select_pop_scale :: (ts: f32) -> f32 {
|
||||
// --- Landing squash-bounce ---------------------------------------------------
|
||||
// A damped wobble on settle: the gem flattens wide-and-short on impact, then a
|
||||
// couple of decaying overshoots. 0 at tl==0 and again past the window (rest).
|
||||
// The shape IS P15.1's `squash_envelope` (board_anim) over the normalized window
|
||||
// tl/LAND_DUR, scaled to a tasteful amplitude — so the per-round fall bounce and
|
||||
// this settle bounce are the EXACT same envelope (P17.3 drives both through here).
|
||||
LAND_DUR :f32: 0.42;
|
||||
LAND_SQUASH_A :f32: 0.13;
|
||||
LAND_OSC :f32: 1.5; // oscillations across the window
|
||||
LAND_SQUASH_A :f32: 0.18; // peak ~13% wide-and-short — reads on landing, still tasteful
|
||||
|
||||
land_squash :: (tl: f32) -> f32 {
|
||||
if tl <= 0.0 or tl >= LAND_DUR { return 0.0; }
|
||||
decay := 1.0 - tl / LAND_DUR;
|
||||
LAND_SQUASH_A * sin(TAU * LAND_OSC * tl / LAND_DUR) * decay * decay
|
||||
LAND_SQUASH_A * squash_envelope(tl / LAND_DUR)
|
||||
}
|
||||
|
||||
// --- Clear pop ---------------------------------------------------------------
|
||||
@@ -117,7 +119,15 @@ GemMotion :: struct {
|
||||
}
|
||||
|
||||
stamp_land :: (self: *GemMotion, i: s64) {
|
||||
self.land_at[i] = self.clock;
|
||||
self.stamp_land_at(i, self.clock);
|
||||
}
|
||||
|
||||
// Record cell `i`'s landing at an explicit clock value, so the settle hand-off
|
||||
// can BACK-DATE the stamp to when the gem actually touched down mid-fall (each
|
||||
// column lands at a staggered instant): land_squash then resumes the per-round
|
||||
// bounce exactly where render_fall left it, with no double-pop at the seam.
|
||||
stamp_land_at :: (self: *GemMotion, i: s64, at: f32) {
|
||||
self.land_at[i] = at;
|
||||
}
|
||||
|
||||
land_local :: (self: *GemMotion, i: s64) -> f32 {
|
||||
|
||||
Reference in New Issue
Block a user