White landing ring: closed-form prediction kills the jitter
predictLanding stepped the trajectory in 10ms chunks and returned the first point past ground level — an overshoot of up to ~25cm that varied per frame, which is what actually jittered (the earlier pixel-snap only addressed sub-pixel shimmer). The landing point of a parabola has an exact solution; computing it directly makes the prediction identical every frame. Measured: max frame-to-frame movement 5.5mm, was ~25cm. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0bf6937121
commit
f2bf21f252
1 file changed
+7
-9
@@ -579,14 +579,12 @@ function update(dt) {
|
||||
if (phase === 'over') { overT -= dt; if (overT <= 0) setupPoint(); }
|
||||
}
|
||||
|
||||
function predictLanding() { // first-bounce point of the ball's current trajectory
|
||||
let { x, y, z, vx, vy, vz } = ball;
|
||||
const g = ball.g || TUNE.gravity, dt = 0.01;
|
||||
for (let i = 0; i < 300; i++) {
|
||||
vy -= g * dt; x += vx * dt; y += vy * dt; z += vz * dt;
|
||||
if (y <= 0) return { x, z };
|
||||
}
|
||||
return null;
|
||||
function predictLanding() { // first-bounce point, closed form — exact, so the ring never jitters
|
||||
const g = ball.g || TUNE.gravity;
|
||||
const disc = ball.vy * ball.vy + 2 * g * ball.y;
|
||||
if (disc < 0) return null;
|
||||
const t = (ball.vy + Math.sqrt(disc)) / g; // time until y = 0
|
||||
return { x: ball.x + ball.vx * t, z: ball.z + ball.vz * t };
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- render ----
|
||||
@@ -739,7 +737,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.5 * (sv.side === 'P' ? 1 : -1), by = Math.abs(Math.sin(idleT * 3.6)) * 0.7; // 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.55; // 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();
|
||||
|
||||
Reference in new issue
Block a user