P11.2: escalating combo emphasis tied to cascade depth (sx / iOS)
Scale the combo FX with cascade depth (mv.rounds.len) — the same depth the cascade SFX (play_cascade) steps up on — so deeper cascades read as more exciting and land in lockstep with the audio escalation. Purely visual and self-pruning: no board / score / move state changes, and input stays gated by BoardAnim.active alone. - board_fx.sx: add fx_combo_level (mirrors audio's cascade_cue_index clamp: depth<=1 -> floor, depth>=5 -> ceiling). The +points popup now carries the cascade depth and grows one font step + lerps gold -> hot-gold per level (fx_popup_font / fx_popup_color). Every burst of a deep cascade gets a whole-move depth boost (FX_BURST_DEPTH) on top of the existing per-round bump. - board_view.sx: render_fx_popups derives styling from depth and tops a combo with a "COMBO xN" label naming the true cascade depth. - tests/fx_combo.sx: headless snapshot locking the depth->level/font table and asserting fx_combo_level matches the cascade-cue index column entry-for-entry. - goldens/p11_combo_deep.png + README: deterministic depth-5 capture (M3TE_FX=11) vs the depth-1 single clear (M3TE_FX=3); FX gone after settle at a later phase.
This commit is contained in:
1
tests/expected/fx_combo.exit
Normal file
1
tests/expected/fx_combo.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
12
tests/expected/fx_combo.stdout
Normal file
12
tests/expected/fx_combo.stdout
Normal file
@@ -0,0 +1,12 @@
|
||||
== combo emphasis selection (depth -> fx level / popup font) ==
|
||||
depth 0 -> level 0 font 34.000000 combo false
|
||||
depth 1 -> level 0 font 34.000000 combo false
|
||||
depth 2 -> level 1 font 48.000000 combo true
|
||||
depth 3 -> level 2 font 56.000000 combo true
|
||||
depth 4 -> level 3 font 64.000000 combo true
|
||||
depth 5 -> level 4 font 72.000000 combo true
|
||||
depth 6 -> level 4 font 72.000000 combo true
|
||||
depth 7 -> level 4 font 72.000000 combo true
|
||||
depth 8 -> level 4 font 72.000000 combo true
|
||||
depth 9 -> level 4 font 72.000000 combo true
|
||||
ok: combo emphasis clamps into level 0..4 in lockstep with the cascade cue
|
||||
57
tests/fx_combo.sx
Normal file
57
tests/fx_combo.sx
Normal file
@@ -0,0 +1,57 @@
|
||||
// P11.2 — Combo-emphasis selection snapshot: prove the cascade-depth → combo-
|
||||
// emphasis mapping is a PURE, headless clamp that steps up in LOCKSTEP with the
|
||||
// cascade SFX cue. The on-screen combo emphasis (`board_fx.sx`'s `fx_combo_level`,
|
||||
// which drives the popup size/colour step + the burst depth boost) must use the
|
||||
// SAME depth→level clamp the audio path uses (`audio.sx`'s `cascade_cue_index`):
|
||||
// depth <= 1 pins to the floor, depth >= 5 to the ceiling, stepping up
|
||||
// monotonically between — so a deeper cascade always looks AND sounds more
|
||||
// escalated. `expect_level` below is exactly the index column locked by
|
||||
// `tests/expected/cascade_cue.stdout`, so any drift on EITHER side breaks a
|
||||
// snapshot. (audio.sx isn't imported here: its AudioToolbox `#foreign` symbols
|
||||
// can't link into the same headless binary as board_fx.sx's GL imports.) The
|
||||
// derived popup-font table is locked by this test's own committed snapshot.
|
||||
#import "modules/std.sx";
|
||||
#import "board_fx.sx";
|
||||
|
||||
main :: () -> s32 {
|
||||
print("== combo emphasis selection (depth -> fx level / popup font) ==\n");
|
||||
|
||||
// The cascade-cue index per depth 0..9, copied from cascade_cue.stdout. The
|
||||
// FX level must equal this entry for entry — the audio/visual lockstep.
|
||||
expect_level : [10]s64 = .{ 0, 0, 1, 2, 3, 4, 4, 4, 4, 4 };
|
||||
|
||||
prev : s64 = -1;
|
||||
for 0..10: (depth) {
|
||||
lvl := fx_combo_level(depth);
|
||||
font := fx_popup_font(depth);
|
||||
combo := depth > 1;
|
||||
print("depth {} -> level {} font {} combo {}\n", depth, lvl, font, combo);
|
||||
if lvl < prev { print("FAIL: fx level decreased at depth {}\n", depth); return 1; }
|
||||
if lvl != expect_level[depth] {
|
||||
print("FAIL: fx level {} != cascade cue index {} at depth {}\n",
|
||||
lvl, expect_level[depth], depth);
|
||||
return 1;
|
||||
}
|
||||
prev = lvl;
|
||||
}
|
||||
|
||||
// Explicit clamp boundaries, independent of the loop above.
|
||||
if fx_combo_level(0) != 0 { print("FAIL: depth 0 not clamped to floor\n"); return 1; }
|
||||
if fx_combo_level(1) != 0 { print("FAIL: depth 1 not clamped to floor\n"); return 1; }
|
||||
if fx_combo_level(5) != FX_COMBO_MAX_LEVEL { print("FAIL: depth 5 not at ceiling\n"); return 1; }
|
||||
if fx_combo_level(9) != FX_COMBO_MAX_LEVEL { print("FAIL: deep cascade not clamped to ceiling\n"); return 1; }
|
||||
|
||||
// A single clear (depth 1) keeps the plain popup font; a combo is strictly
|
||||
// larger and the font never shrinks as the cascade deepens.
|
||||
if fx_popup_font(1) != FX_POPUP_FONT { print("FAIL: single-clear popup not plain font\n"); return 1; }
|
||||
pf : f32 = 0.0;
|
||||
for 2..10: (depth) {
|
||||
f := fx_popup_font(depth);
|
||||
if f <= FX_POPUP_FONT { print("FAIL: combo popup not larger than plain at depth {}\n", depth); return 1; }
|
||||
if depth > 2 and f < pf { print("FAIL: popup font shrank at depth {}\n", depth); return 1; }
|
||||
pf = f;
|
||||
}
|
||||
|
||||
print("ok: combo emphasis clamps into level 0..{} in lockstep with the cascade cue\n", FX_COMBO_MAX_LEVEL);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user