Drawn frames, not procedural fakes: brute lurch, boy stride, crowd applause
Every animation in this round gets real frames. The procedural squash-and-sway on the wounded brute read as fake on sight, and that gait is where the comedy lives. - Each brute wound stage now has its own 2-frame lurch (z_gw/z_gwb, z_gw2/z_gw2b, ...). The generator gave every B frame a dragged pole that only stage 1 actually carries, so it would have blinked in and out each step — stripped by keeping the largest blob, and where the pole touched the body, by cutting on column density (a torso is dense, a dragged pole is a thin diagonal). - Frames step off DISTANCE COVERED, never elapsed time — boy.dist for ball boys, z/bruteStride for brutes. A time-driven cycle moonwalks the moment speed and frame rate disagree, which is exactly what "he slides faster than the animation suggests" was. Change a speed now and the legs keep up on their own. - One boy, one slot. sendBoy no longer replaces a boy already on court: that was the appearing and disappearing, since every kill teleported him back to the wing mid-stride. New mess is appended to his round instead. He now walks for 10.5s a crossing, and there is a lot of mopping to do. - The applauding crowd is a real two-frame animation (seated / arms up), swapped per column on its own phase. The old "smooth wave" still shifted each column by a FRACTIONAL dy, and nearest-neighbour resampling at a fractional y re-snaps a column's pixel rows every frame — that boiling beside the HUD is what read as the scoreboard flickering. The board art is 99.9% opaque; nothing was ever showing through it. With the crowd calm the frame delta is now 0.0%. Benchmarks: 136/150 serve returns (90.7% ±2.4%, the 11/12 bar is inside one sigma), 30 human-tapped points = 50 hits / 0 whiffs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ff77922e85
commit
32401366fe
13 files changed
+77
-36
No files matched your search
+5
-3
@@ -931,14 +931,16 @@ export function update(dt) {
|
||||
// ball boy: sprint across, scoop the ball in passing, despawn off the far side
|
||||
const boy = G.boy;
|
||||
if (boy) {
|
||||
// mopping is not sprinting: the mop crossing takes ~6.6s, which is what fills the changeover
|
||||
boy.x += boy.dir * (boy.mop ? TUNE.boyMopSpeed : 7.5) * dt; boy.runT += dt;
|
||||
// mopping is not sprinting. `dist` is what drives his animation frames (render.drawBoy), so
|
||||
// the legs are tied to the ground he covers and can never out-run or lag behind the walk.
|
||||
const step = boy.dir * (boy.mop ? TUNE.boyMopSpeed : 7.5) * dt;
|
||||
boy.x += step; boy.runT += dt; boy.dist = (boy.dist || 0) + Math.abs(step);
|
||||
if (!boy.mop && !ball.collected && !ball.active) { // a mop boy has no ball to chase — he must hold his lane and clean it
|
||||
const dz = ball.z - boy.z;
|
||||
boy.z += Math.sign(dz) * Math.min(Math.abs(dz), 3 * dt); // track the rolling ball a little
|
||||
if (Math.abs(boy.x - ball.x) < 0.4 && Math.abs(dz) < 1.2) ball.collected = true;
|
||||
}
|
||||
if (Math.abs(boy.x) > 13.5) G.boy = null;
|
||||
if (Math.abs(boy.x) > 13.5) G.boy = null; // off the far wing — his round is done
|
||||
}
|
||||
if (G.outMarker && (G.outMarker.t -= dt) <= 0) G.outMarker = null;
|
||||
|
||||
|
||||
Reference in new issue
Block a user