diff --git a/assets/speech/trestle/trestle-q4-04.mp3 b/assets/speech/trestle/trestle-q4-04.mp3 new file mode 100644 index 0000000..614a89c Binary files /dev/null and b/assets/speech/trestle/trestle-q4-04.mp3 differ diff --git a/assets/speech/trestle/trestle-q4-05.mp3 b/assets/speech/trestle/trestle-q4-05.mp3 new file mode 100644 index 0000000..c2b190f Binary files /dev/null and b/assets/speech/trestle/trestle-q4-05.mp3 differ diff --git a/dev/marquee.test.mjs b/dev/marquee.test.mjs index 7d74894..10fb298 100644 --- a/dev/marquee.test.mjs +++ b/dev/marquee.test.mjs @@ -17,6 +17,9 @@ * ones. * - BUFFER — a level-up landing MID-BEAT is buffered and plays right * after the live one (the queue never drops a level). + * - LOCK — the digit slots lock onto the FINAL level on any scene + * clock (the lock stamps are ELAPSED beat time, not scene + * time — a live session's clock must lock like a zero one). * - TEARDOWN — destroy() ends the beat and every created object dies * with the scene (a scene mid-shutdown can't wedge it). * @@ -263,4 +266,25 @@ const settled = (m) => console.log('ok 5 — the cap level plays the MAXED line'); } +// --------------------------------------------------------------------------- +// 6 — LOCK ON A LIVE CLOCK (the digit locks compare ELAPSED beat time, so +// a scene whose clock is minutes in must lock the same as one at zero — +// the regression where c.lockAt was stamped as an ABSOLUTE scene time +// and `el >= c.lockAt` never held, leaving the slots cycling random +// values off the level the player actually reached) +// --------------------------------------------------------------------------- +{ + const scene = makeScene(); + scene.time.now = 60000; // a real session's clock, not the zero origin + const m = new LevelUpMarquee(scene); + m.play({ from: 7, to: 9 }); + // Step just past the last lock (the rightmost locks at T.lockBase, the + // leftmost at T.lastLock) and check the slots read the FINAL digits. + step(m, scene, () => scene.time.now - m.t0 >= m.T.lastLock + 200, 5000); + assert.equal(m._digitCols[0].gt.main.text, '0', 'the left slot locked onto the final digit'); + assert.equal(m._digitCols[1].gt.main.text, '9', 'the right slot locked onto the final digit'); + step(m, scene, () => settled(m), 20000); + console.log('ok 6 — the digit locks land on a non-zero scene clock'); +} + console.log('\nmarquee: all checks passed'); diff --git a/dev/shots/marquee-lock.png b/dev/shots/marquee-lock.png index 936ad33..bb8362f 100644 Binary files a/dev/shots/marquee-lock.png and b/dev/shots/marquee-lock.png differ diff --git a/dev/shots/marquee-max.png b/dev/shots/marquee-max.png index d72ef4f..b797797 100644 Binary files a/dev/shots/marquee-max.png and b/dev/shots/marquee-max.png differ diff --git a/dev/shots/marquee-old.png b/dev/shots/marquee-old.png index 6981dcd..faeafab 100644 Binary files a/dev/shots/marquee-old.png and b/dev/shots/marquee-old.png differ diff --git a/dev/shots/marquee-peel.png b/dev/shots/marquee-peel.png index 10c4504..1c12ca2 100644 Binary files a/dev/shots/marquee-peel.png and b/dev/shots/marquee-peel.png differ diff --git a/dev/shots/marquee-scramble.png b/dev/shots/marquee-scramble.png index e9c6ba4..7eb0241 100644 Binary files a/dev/shots/marquee-scramble.png and b/dev/shots/marquee-scramble.png differ diff --git a/dev/shots/marquee-shatter.png b/dev/shots/marquee-shatter.png index 592fc28..43cbd2f 100644 Binary files a/dev/shots/marquee-shatter.png and b/dev/shots/marquee-shatter.png differ diff --git a/dev/shots/marquee-sync.png b/dev/shots/marquee-sync.png index 0ab9bcb..c7e9eed 100644 Binary files a/dev/shots/marquee-sync.png and b/dev/shots/marquee-sync.png differ diff --git a/js/ui/LevelUpMarquee.js b/js/ui/LevelUpMarquee.js index 493c78f..8804e10 100644 --- a/js/ui/LevelUpMarquee.js +++ b/js/ui/LevelUpMarquee.js @@ -402,7 +402,12 @@ export class LevelUpMarquee { for (const p of newBoard.parts) p.gt.setVisible(false); this._digitCols.forEach((c, i) => { c.final = c.ch; - c.lockAt = this.t0 + this.T.lockBase + (D - 1 - i) * 140; // i = from the left + // ELAPSED ms since the beat start (update() compares it against + // el = time - t0) — NOT a scene-clock stamp: on a live session + // s.time.now is minutes in, and an absolute stamp would make + // `el >= c.lockAt` false for the whole beat, so the digit never + // locks and the slots keep cycling random values off the level. + c.lockAt = this.T.lockBase + (D - 1 - i) * 140; // i = from the left c.bucket = -1; c.phase = i * 1.7; });