P10.3: wire the SFX bank to game events (sx / iOS)
Drive event-appropriate cues from the existing System Sound Services bank, purely additively — no board/score/move state is read or written and every call stays inline-if-OS==.ios guarded. board_view.sx (move-commit path): a committed gesture now plays the swap slide cue for any swipe intent (legal or the reverted ping-back); a legal move adds the match pop on its first clearing round; a multi-round chain adds the escalating cascade cue keyed to the recorded AnimMove depth (mv.rounds.len), kept distinct from the match pop so a single clear is never doubled. An illegal swap plays only the swap cue. main.sx (frame loop): the win/lose stinger fires EXACTLY ONCE, edge-triggered on the frame the banner comes up — the level has settled won/lost and any in-flight cascade has finished animating. Status is read-only from the model; a restart re-arms the edge for a fresh win/lose. audio.sx: each play_* method logs a per-cue NSLog line at play time so the ordering is observable via `log show`; cascade_cue_name maps the clamped combo index to a stable literal (literals only — the string→NSString bridge needs NUL-terminated bytes).
This commit is contained in:
25
audio.sx
25
audio.sx
@@ -67,12 +67,14 @@ GameAudio :: struct {
|
||||
play_swap :: (self: *GameAudio) {
|
||||
inline if OS != .ios { return; }
|
||||
if !self.loaded { return; }
|
||||
NSLog(xx "[sx] audio: cue swap");
|
||||
AudioServicesPlaySystemSound(self.swap_id);
|
||||
}
|
||||
|
||||
play_match :: (self: *GameAudio) {
|
||||
inline if OS != .ios { return; }
|
||||
if !self.loaded { return; }
|
||||
NSLog(xx "[sx] audio: cue match");
|
||||
AudioServicesPlaySystemSound(self.match_id);
|
||||
}
|
||||
|
||||
@@ -81,22 +83,38 @@ GameAudio :: struct {
|
||||
play_cascade :: (self: *GameAudio, depth: s64) {
|
||||
inline if OS != .ios { return; }
|
||||
if !self.loaded { return; }
|
||||
AudioServicesPlaySystemSound(self.combo_ids[cascade_cue_index(depth)]);
|
||||
idx := cascade_cue_index(depth);
|
||||
NSLog(xx cascade_cue_name(idx));
|
||||
AudioServicesPlaySystemSound(self.combo_ids[idx]);
|
||||
}
|
||||
|
||||
play_win :: (self: *GameAudio) {
|
||||
inline if OS != .ios { return; }
|
||||
if !self.loaded { return; }
|
||||
NSLog(xx "[sx] audio: cue win");
|
||||
AudioServicesPlaySystemSound(self.win_id);
|
||||
}
|
||||
|
||||
play_lose :: (self: *GameAudio) {
|
||||
inline if OS != .ios { return; }
|
||||
if !self.loaded { return; }
|
||||
NSLog(xx "[sx] audio: cue lose");
|
||||
AudioServicesPlaySystemSound(self.lose_id);
|
||||
}
|
||||
}
|
||||
|
||||
// The cascade cue's log line, one stable literal per combo clip so the play-time
|
||||
// `log show` shows the clip stepping up with cascade depth. Literals only — the
|
||||
// string→NSString bridge needs NUL-terminated bytes (a formatted string may not
|
||||
// be). `idx` is a clamped `cascade_cue_index`, so it is always 0..COMBO_CLIPS-1.
|
||||
cascade_cue_name :: (idx: s64) -> string {
|
||||
if idx <= 0 { return "[sx] audio: cue combo1"; }
|
||||
if idx == 1 { return "[sx] audio: cue combo2"; }
|
||||
if idx == 2 { return "[sx] audio: cue combo3"; }
|
||||
if idx == 3 { return "[sx] audio: cue combo4"; }
|
||||
"[sx] audio: cue combo5"
|
||||
}
|
||||
|
||||
// Cascade depth (number of cleared rounds) → combo clip index 0..COMBO_CLIPS-1
|
||||
// (combo1..combo5). Clamps: depth <= 1 → 0, depth >= 5 → 4. Pure arithmetic and
|
||||
// OS-agnostic so it can be snapshot-tested headlessly (P10.4).
|
||||
@@ -144,8 +162,9 @@ load_system_sound :: (name: string) -> u32 {
|
||||
}
|
||||
|
||||
// The process-wide instance. main() allocates + inits it; board_view triggers
|
||||
// cues through the `sfx_*` shims. Null until init, so every shim is a safe
|
||||
// no-op before then. Event→cue wiring beyond cascade lands in P10.3.
|
||||
// the swap/match/cascade cues through the `sfx_*` shims on a committed gesture,
|
||||
// and main's frame loop fires the win/lose stinger edge-triggered. Null until
|
||||
// init, so every shim is a safe no-op before then.
|
||||
g_audio : *GameAudio = null;
|
||||
|
||||
sfx_swap :: () { if g_audio != null { g_audio.play_swap(); } }
|
||||
|
||||
Reference in New Issue
Block a user