P17.1: organic fall — accelerate under gravity (ease_in_cubic)

render_fall now drives the per-round drop with ease_in_cubic (P15.1 accel-from-
rest) instead of ease_out_cubic, so falling gems start slow and accelerate into
place like gravity rather than decelerating. f(1)=1 is pinned, so every gem still
lands exactly on its destination cell and move.final is untouched. FALL_ANIM_DUR
(0.22s) is unchanged, so the cascade-cue timing snapshots don't churn.

Golden goldens/p17_fall.png: M3TE_FX=11 (depth-5 cascade, seed 1337) pinned at
M3TE_ANIM_TIME=1.51 (round 3 fall window [1.38,1.60)) — gems caught bunched-high
mid-fall, ~20% down at ~59% of the segment, vs the old curve's ~93%.
This commit is contained in:
swipelab
2026-06-06 11:15:10 +03:00
parent fa2d4c09f2
commit f68ed9a2b3
4 changed files with 41 additions and 5 deletions

View File

@@ -275,6 +275,40 @@ env SIMCTL_CHILD_M3TE_BADSWAP=41 SIMCTL_CHILD_M3TE_ANIM_TIME=0 \
xcrun simctl launch --terminate-running-process booted co.swipelab.m3te
```
### Organic fall — gravity accel (P17.1)
Falling gems no longer *decelerate* into place: `render_fall` now drives the
per-round drop with `ease_in_cubic` (the P15.1 accelerate-from-rest curve) instead
of `ease_out_cubic`, so gems start slow and accelerate down like gravity. The curve
pins `f(0)=0` and `f(1)=1`, so each gem still lands EXACTLY on its destination cell
at the segment's end — the seam to the next round / settled board stays invisible
and `move.final` is untouched (`tests/anim_plan.sx` contiguity stays green).
`FALL_ANIM_DUR` (0.22 s) is unchanged, so the per-round cascade-cue timing
snapshots (`tests/cascade_rounds.sx` / `cascade_cue.sx`) don't churn.
The visual tell of the accel: pinned mid-fall, gems are bunched HIGH near their
sources (little distance covered) rather than spread out near landing. Capture it
with the `M3TE_FX` hook; `M3TE_FX=11` is the depth-5 cascade on seed 1337, pinned
inside **round 3's fall window** `[1.38, 1.60)` s — at `1.51` we are ~59 % through
that segment in time, yet `ease_in_cubic(0.59) ≈ 0.20`, so the gems have covered
only ~20 % of their drop and hang caught in the upper rows over the filled lower
board (the old `ease_out_cubic(0.59) ≈ 0.93` would have them ~93 % down, all but
landed):
```bash
# Gems caught bunched-high mid-fall under gravity accel: goldens/p17_fall.png
env SIMCTL_CHILD_M3TE_FX=11 SIMCTL_CHILD_M3TE_ANIM_TIME=1.51 \
xcrun simctl launch --terminate-running-process booted co.swipelab.m3te
# Same cascade past the timeline — fully settled board (no golden):
env SIMCTL_CHILD_M3TE_FX=11 SIMCTL_CHILD_M3TE_ANIM_TIME=3.0 \
xcrun simctl launch --terminate-running-process booted co.swipelab.m3te
```
The round-k fall window is `[0.30 + 0.36·k, 0.52 + 0.36·k)` s on the
swap→(clear,fall)\* timeline (swap 0.16, then clear 0.14 + fall 0.22 per round), so
`1.51` lands squarely in round 3's fall. The change is render-only — no `board.sx`
model change, and normal play is byte-identical apart from the fall's motion curve.
## Audio bank (P10) — final model
The SFX bank (`audio.sx`) is a purely additive layer over iOS **System Sound

View File

@@ -23,8 +23,8 @@ SWAP_ANIM_DUR :f32: 0.16;
CLEAR_ANIM_DUR :f32: 0.14;
FALL_ANIM_DUR :f32: 0.22;
// Easing helpers. Slide/fall decelerate into place (ease-out cubic); the clear
// scale-out accelerates as it shrinks (ease-in quad).
// Two base easing helpers, each with locked endpoints f(0)=0 and f(1)=1:
// ease_out_cubic decelerates into its endpoint, ease_in_quad accelerates from rest.
ease_out_cubic :: (t: f32) -> f32 { u := t - 1.0; u * u * u + 1.0 }
ease_in_quad :: (t: f32) -> f32 { t * t }

View File

@@ -529,10 +529,12 @@ BoardView :: struct {
}
}
// Fall segment: every gem of the round's settled board slides from its source
// row (above the board for refills) down to its destination cell.
// Fall segment: every gem of the round's settled board accelerates under
// gravity from its source row (above the board for refills) down to its
// destination cell. ease_in_cubic pins f(1)=1, so each gem lands exactly on
// its cell and the seam to the next round / settled board stays invisible.
render_fall :: (self: *BoardView, ctx: *RenderContext, rd: *AnimRound, inset: f32, dim: f32, t: f32) {
te := ease_out_cubic(t);
te := ease_in_cubic(t);
for 0..BOARD_CELLS: (i) {
g := rd.after[i];
if g == .empty { continue; }

BIN
goldens/p17_fall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB