The bob rides the stride, and the stride finds its beat: runHz2 3.4

Two live verdicts off the bench. The 1px run bob was a fixed 18 Hz wall-clock
toggle — over the calm two-frame cycle it read as independent HOPPING — so it
now shares the exact phase counter that flips the frames: one dip per step,
always in sync at any cadence. And with bob and feet locked together the
cadence itself came up for retuning: 1.7 read as a jog, doubled to 3.4 it is
a run — "that's it! way better." One knob moves both, which is what made the
doubling a one-word change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Fable 5 committed 2026-08-14 14:57:16 +02:00
1 parent 40c74be4aa
commit f62c7ff0ff
3 files changed
+7 -4

No files matched your search

+1 -1
View File
@@ -494,6 +494,6 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
</div>
</div>
</div>
<script type="module" src="src/main.js?v=248"></script>
<script type="module" src="src/main.js?v=249"></script>
</body>
</html>
+3 -2
View File
@@ -42,8 +42,9 @@ export const TUNE = {
serveHardErr: 1.6,// how much a hard serve multiplies the timing scatter: pace is paid for in
// faults, which is what makes tap = safe second serve a real decision
runN: 0, // frame-count override for run cycles (0 = probe per character sheet) — bench tuning knob
runHz2: 1.7, // stride cycles/s for TWO-frame pairs (the opponents). Tuned live on the bench
// with Oliver 2026-08-14 — the old hardcoded 4.5 was strobe; 1.7 reads as running.
runHz2: 3.4, // stride cycles/s for TWO-frame pairs (the opponents). Tuned live on the bench
// with Oliver 2026-08-14: 4.5 on six frames was strobe, 1.7 on two read as jogging,
// and 3.4 with the stride-synced bob is the one he called "way better".
runHz: 2.4, // stride cycles/s for the rolled 6/8-frame run sets. The old hardcoded 4.5 was
// tuned on 2-4 near-duplicate frames; on eight real phases it strobed
faceFlip: 0.13, // s an auto-steered direction must persist before the body mirrors (earnFlip).
+3 -1
View File
@@ -1498,7 +1498,9 @@ function drawChar(ch) {
// the spot, because the run frames are a full leaning stride, not a ready-hop. He idles now.)
if (ch.pose === 'swing') name = pre + (ch.poseT < 0.15 ? 'swing1' : 'swing2');
if (ch.pose === 'serve') name = pre + (G.phase === 'toss' ? 'toss' : 'smash');
if (ch.pose === 'run') p.y -= Math.floor(ch.runT * 18) % 2; // 1px run bob
// the run bob rides the STRIDE, not a wall clock: one dip per step, in phase with the frame
// flip — the old fixed 18 Hz toggle read as independent hopping over the calm 2-frame cycle
if (ch.pose === 'run') p.y -= Math.floor(ch.runT * (runN >= 6 ? TUNE.runHz : TUNE.runHz2) * runN) % 2;
const img = SPR[SK(name)];
drawShadow(p.x, p.y, hpx * 0.22, hpx * 0.06);
if (img) {