Cut the serve down to three poses

Oliver, after playing the four-stage version on the phone: idle, then the racket
dropping on the pull, then the drive on release — "that's all, forget all the
others". At thumb speed the middle stages are never read, so they are deleted
rather than kept around: p_pull is the wind-up, p_smash is the drive, and both
come out of the photo-referenced sheet, so the whole serve is one drawing style.

The dead batches and the arm_left guard go with them. assets/_pose_ref_serve.png
is kept as the recipe: his photo sequence over our own sprites, which is what
turned a fifteen-generation prose argument into one generation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-01 01:09:57 +02:00
1 parent f6dfc57a06
commit 6378ff2a1b
11 files changed
+30 -97

No files matched your search

+9 -12
View File
@@ -3,7 +3,7 @@
import { cv, ctx } from './dom.js';
import { TUNE, UI, EATEN_GRAB, EATEN_BURST, EATEN_SUMMARY, EATEN_RESTART, COURT, PLAYER_H, BOY_H, UMP_H, UMP_X, MACH_H, BOSS_ART, BOUNCE_IDLE, SPRITE_H } from './config.js';
import { P, O, ball, score, crowd, G } from './state.js';
import { predictLanding, flickTarget, pullFrac } from './gameplay.js';
import { predictLanding, flickTarget } from './gameplay.js';
import { zombies, gore, piles, parts, pellets, extras, shots } from './zombies.js';
// ---------------------------------------------------------------- palette ----
@@ -155,10 +155,10 @@ export function proj(x, y, z) {
// ---------------------------------------------------------------- sprites ----
// assets/<name>.png; game falls back to code-drawn figures until sprites load.
const SPRV = 72; // asset cache-buster — bump with main.js?v=N (see the img.src note below)
const SPRV = 73; // asset cache-buster — bump with main.js?v=N (see the img.src note below)
const SPR = {};
for (const n of ['p_idle1','p_idle2','p_bounce','p_bounce2','p_toss','p_smash','p_run1','p_run2','p_run3','p_run4','p_swing1','p_swing2','p_die1','p_die2','p_die3','p_die4','p_die5',
'p_pull1','p_pull2','p_pull3','p_pull4', // the serve WIND-UP, one frame per quarter of the pull (see drawChar)
'p_pull', // the serve wind-up: the racket dropping behind him while the pull is drawn
'o_idle1','o_idle2','o_bounce','o_bounce2','o_toss','o_smash','o_run1','o_run2','o_swing1','o_swing2',
'x_ump','x_boyrun1','x_boyrun2','x_boyrun3','x_boyrun4','x_crowd','x_crowd2','x_ads',
'x_boymop1','x_boymop2','x_boymop3','x_boymop4', // the push cycle, used only while he is stopped and working
@@ -485,15 +485,12 @@ function drawChar(ch) {
// the ground. BOUNCE_IDLE.apex is measured off that palm, so the ball meets it.
name = pre + (Math.abs(Math.sin(G.idleT * BOUNCE_IDLE.tempo)) > 0.5 ? 'bounce2' : 'bounce');
}
// THE PULL IS THE WIND-UP. While the slingshot is drawn, the frame is chosen by how far back the
// finger has come: racket above the head -> behind the head -> behind the back -> fully coiled,
// and the release snaps to p_smash. The stages are NOT spread evenly over the pull: frame 1 owns
// the whole first half and the three coiled frames are packed into the top half, so the part of
// the gesture that costs power is the part that visibly costs effort.
if (G.aim && G.aim.mag > 0 && ch.side === 'P' && score.server === 'P' && ch.pose === 'idle') {
const f = pullFrac(G.aim.mag);
name = 'p_pull' + (f < 0.5 ? 1 : Math.min(4, 2 + Math.floor((f - 0.5) * 6)));
}
// THE PULL IS THE WIND-UP — three poses, not a scrubbable animation. Waiting: the bounce stance.
// Drawing the slingshot: `p_pull`, the racket dropping behind him. Release: `p_smash`, the drive.
// A four-stage version keyed to pullFrac was built and played, and Oliver cut it back to this:
// on a phone, at thumb speed, the middle stages are never read — the three states are the beat.
if (G.aim && G.aim.mag > 0 && ch.side === 'P' && score.server === 'P' && ch.pose === 'idle')
name = 'p_pull';
// Four-frame run where the frames exist (the player), two where they don't (the opponent). Same
// CYCLE rate either way — more frames subdivide the stride, they do not speed it up, exactly as
// ZFRAMES does for the shamblers.