From 0bf69371210fa07fc0586e60fe5d83a7ed0387ae Mon Sep 17 00:00:00 2001 From: Oliver Rieger Date: Sat, 11 Jul 2026 15:18:32 +0200 Subject: [PATCH] Serve bounce sprite switches exactly at the ball's apex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hand-raised frame while the ball rises, pat-down frame from the apex on — synced to the ball's direction instead of a height threshold. Includes Oliver's hand-tuned ball offset. Co-Authored-By: Claude Fable 5 --- game.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/game.js b/game.js index e3fca59..a93488e 100644 --- a/game.js +++ b/game.js @@ -638,8 +638,11 @@ function drawChar(ch) { // pick sprite const pre = ch.side === 'P' ? 'p_' : 'o_'; let name = pre + (Math.floor(idleT * 1.6) % 2 ? 'idle1' : 'idle2'); // idle weight shift - if (phase === 'pretoss' && ch.side === score.server && ch.pose === 'idle') - name = pre + (Math.abs(Math.sin(idleT * 3.6)) > 0.55 ? 'bounce2' : 'bounce'); // hand rises as the ball comes up + if (phase === 'pretoss' && ch.side === score.server && ch.pose === 'idle') { + const w = idleT * 3.6; // same phase as the bouncing ball + const rising = Math.sin(w) * Math.cos(w) > 0; + name = pre + (rising ? 'bounce2' : 'bounce'); // hand up while the ball rises, pat down exactly at the apex + } if (ch.pose === 'run') name = pre + (Math.floor(ch.runT * 9) % 2 ? 'run1' : 'run2'); if (receiverWaiting) name = pre + (sway > 0 ? 'run1' : 'run2'); // split-step shuffle if (ch.pose === 'swing') name = pre + (ch.poseT < 0.15 ? 'swing1' : 'swing2'); @@ -736,7 +739,7 @@ function render() { // server idly bouncing the ball while waiting if (phase === 'pretoss') { const sv = score.server === 'P' ? P : O; - const bx = sv.x - 0.32 * (sv.side === 'P' ? 1 : -1), by = Math.abs(Math.sin(idleT * 3.6)) * 0.78; // floor to the reaching hand + const bx = sv.x - 0.5 * (sv.side === 'P' ? 1 : -1), by = Math.abs(Math.sin(idleT * 3.6)) * 0.7; // floor to the reaching hand const sh = proj(bx, 0, sv.z); ctx.fillStyle = 'rgba(0,0,0,0.3)'; ctx.beginPath(); ctx.ellipse(sh.x, sh.y, Math.max(1.5, sh.s * 0.08), Math.max(1, sh.s * 0.035), 0, 0, 7); ctx.fill();