80bf6c4ceeebe275914bba422b573a1c3d97d332
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
eb0e8775a4 |
The timing cues were match-only, and the walk cycles bounced
CLASSIC TENNIS, third time asked and this time actually found. Both cues open with a mode gate and I checked the wrong two features twice: drawApproachRing (the closing circles that show when to tap) and drawApexBand (the serve bar with the gold perfect window) each began `if (!G.match ...)`. So the mode whose whole pitch is "if the core tennis is good everything else is good" was the one mode with neither. They run on `G.match || G.mode === 'tennis'` now — the gore mode stays out on purpose, there is no rally there. A test reads both function bodies and fails if either is ever gated on the match alone again. (The two I kept pointing at — the landing ring and the placement ring — really are shared. They were just not the ones being asked about.) THE BOUNCING WAS IN THE ART, and measurable: the six generated families came back with the shuffle frame 30-44 px shorter than the stance it walks out of, against 9 px on the hand-made racket family. The game draws every frame at its own PNG height, so the body rose and dropped once per step. A walk cycle is one drawing with the legs moved and must be one height; _zsheet levels the stance and the stride pair now and leaves the forehand its own, exactly as the serve and the fall keep theirs. All seven families re-cut: spreads are 1-8 px. THE BENCH GETS BUTTONS. Arrow keys are not a control scheme on a phone, which is the device the walk has to be judged on — so every family and every wound stage was unreachable from the place the problem shows. Three on-screen pads: BODY, WOUND, POSE, the two-way ones split left/right. Geometry lives beside the drawing and input hit-tests the same function, the rule the rack established. THE FALL is quicker still (0.05/0.07/2.0/0.30): drop, lie there, get up. Three umpire lines pulled — ump_wound_you, ump_felled, ump_wound_opp2. Not funny enough to keep. Files deleted, call sites collapsed to the two that stay. 60 tests green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e1ce2486c0 |
SERVE UP was dropping you into gore whatever you picked
THE MENU BUG, and it explains three reports at once. cStart's handler was
`addEventListener('click', start)` — and addEventListener hands a listener the
MouseEvent as its first argument, so `start(modeId = pickedMode)` never saw its
default: modeId was an EVENT OBJECT. `G.classic = modeId === 'classic'` was
therefore always false and the zombie branch never fired. Picking CLASSIC or
ZOMBIE TENNIS on the setup screen did nothing at all; SERVE UP always started
the gore mode. A default parameter only applies to `undefined`, and a click
handler always passes something. `() => start()`.
That is also why "in normal tennis i dont see the ball circles and the serve
hint bar": there was no normal tennis to be in. Both are drawn unconditionally
in render() and the tennis struggle hints are already mode-gated correctly.
Verified through the real menu after the fix: CLASSIC gives mode=tennis with
no bodies on court, ZOMBIE gives match=true against the SHAMBLER in its own
body. Every other bare handler in the codebase takes no parameters — checked.
THE MOP BOY had the same class of bug one layer down. sendBoy was called and
mopWorthIt() refused: it tests `d.z >= COURT.netZ - 2`, the NEAR half, because
in the gore mode everything dies on the near court. A match's blood is all on
the FAR side, where the body stands and bleeds through four wound stages, so
the boy could never qualify. The near-side bias stays; the match is the
exception.
DANIEL was being dropped, not missing. Two causes, both mine: the asides were
queued at 0.7-1.5 s and matchPoint fires the score call at 0.4 s with a clip
over a second long — voice() drops anything that would start while he is still
talking (one man, one microphone). And asideEvery is 55 s, a whole match game.
Delays moved past the score call; matchAsideEvery is 15 s, which fits a mode
whose events are a limb and your blood rather than a wave of bodies.
THE FALL: quicker down, longer on the floor (0.09/0.11/2.0/0.30). And it was
genuinely SHRUNKEN — the generator draws fall rows smaller than standing rows
(the brute's buckle came back 190 px against a 224 px stance) and _zsheet's one
global scale preserved that faithfully, so the body shrank the moment it
started to fall. A fall row is anchored on its own buckle now, which must draw
at standing height. All seven generated families re-cut: 224/153/98/181 against
the hand-made racket family's 224/154/85/179 — the convergence is the check.
THE FLICK: 0.42 made going out impossible, which fixed the 8-in-10 bug and
overshot it ("too easy. i must be able to play out"). 0.62 puts risk back where
it belongs — ~15% out at quality 0, 5% at 0.75, and never on a perfect flick.
The test now asserts that shape: bounded, monotonically falling, zero at 1.
59 tests green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
cba2fb8a8b |
One roll, one character: the whole zombie family from a single sheet
Nine sheets meant nine chances for the character to drift, and all day it took
every one of them — a brute that was three different brutes, a corpse that came
back a living man. Asking for the WHOLE family in one image removes that by
construction: one roll, one light, one palette, 31 figures.
What was missing was the way back down. _fine.py cuts a single row; a family
sheet is nine. _zsheet.py is that step and nothing else — it reuses _fine's
keyer, block detection and column cutter, and adds the two things that have to
be GLOBAL or the family breaks:
SCALE taken once from the play row's standing frame. Per-band scaling would
make the serve strike the same height as the idle stance, and the game
sizes a sprite off its own PNG height. Measured after: serve 319,
prone fall 83 — the racket family's are 307 and 85.
PALETTE taken once from the largest figure anywhere, so a wound row cannot
quantise onto slightly different colours than the row above it.
The enclosed magenta rule is INVERTED here, deliberately. _fine.py repaints
magenta trapped inside a figure because the generator used to fill string beds
with the backdrop colour by accident. This sheet asks for exactly that and gets
it, so the bed cuts to transparency and the racket is an open hoop.
_regen.py keeps three fixes found on the way: margins as a PROPORTION (an
absolute pixel margin means nothing to a model that picks its own resolution —
it clipped 3 rolls in 4), reference sheets that fill keyed-out string beds
instead of showing the model a magenta racket, and --verify, which asks the
question no gate here ever asked: is the art already on disk what it claims to
be. It found 27 of the brute's 31 frames dead — z_brw1fall was one drawing
pasted four times, 0.011 apart where a real sequence is 0.53.
The brute is live: ZFAMS gains 'br', the KEEPER wears it. Verified in #bench,
healthy and arm-off, 54 tests green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|