4 Commits
Author SHA1 Message Date
wuwiandClaude Opus 5 0c499b60b5 Automate the redraw, and run the first eight batches through it
assets/_regen.py plus a batch file: build a reference sheet from the sprites in
the repo, ask for a HIGH-resolution redraw, slice with _fine.py, colour-match
each frame onto the one it replaces, install. The point of the whole thing is the
style block — the old prompts specified coarse art and got it.

It refuses to install a bad sheet. Wrong frame count, any figure touching a
canvas edge (that is what clipped z_f1 in the first place), or a redraw that is
not measurably finer than what it replaces, and the batch is left alone with a
reason printed. Re-running a batch is the fix; three of the first eleven needed
it. The bar is 1.25x inner-edge density rather than 1.5x, because a sheet that
already has blood on it starts high and a genuinely finer wounded body still
scores a smaller gain.

Done so far: both shamblers and their wound skins, the brute's walk and its two
sets of wound stages, the steward and his wound skins, the turned CPU.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 21:43:58 +02:00
wuwiandClaude Opus 5 7d307d90b9 Four frames for the chair spectator and the turned CPU
The last two bodies still shuffling on two frames. Both get their in-between
strides, generated against their own art and fitted per channel onto it.

The chair-down stagger was walk frame 3, which a four-frame cycle would have
walked straight through — it is its own sprite now (z_sdown), picked by state
rather than by where the cycle happens to be.

Also fixed a strobe that predates all of this: z_c2's racket was drawn BLUE
while every other frame of the same zombie carries a brown one, so it flashed
once per cycle. Remapped onto z_c1's racket palette.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 20:10:20 +02:00
wuwiandClaude Opus 5 49d391dc64 Make it readable: 2x sprites, a flatter camera, honest hit timing
The umpire is situational again. Each line is tied to the thing that justifies
it — a new variant appearing, the court filling, one crossing your baseline, a
game lost, a horde, a changeover — behind one shared cooldown, so several
triggers at once still yield one remark. The random timer pool is gone, the
interval went 26s to 55s, and ump_out_of_order, ump_let and ump_no_appeal are
deleted.

"Visually the ball is not yet at the player but somehow the player already is
hit" was real and measurable. The hostile-ball hit test reused the parry's
hypot(dx, dz*0.8), and weighting depth shrinks it: contact fired while the ball
was still 0.68 m up-court and drawn up around his head. It has its own
unweighted test now, and contact lands at 0.25 m with the ball on his chest.
The parry keeps its weighting — a racket sweep really is wider than it is deep.

On "everything is a tad too small": measured first, because higher-resolution
sprites are only half the answer. At RES 3 the player rasterises into 170
device pixels from a 112px source — upscaled 1.5x — while a far shambler is
downscaled to 78. So near bodies needed resolution and far bodies needed the
camera.

Camera: pushed back and lengthened (camZ 42->48, camF 580->760) to flatten the
perspective so distant bodies grow relative to near ones rather than everything
zooming, camY raised for a steeper look-down, horizon re-centred. Far shambler
26->30px, boss 39->45px, player unchanged, court in the same band.

Sprites: the original sheets were still in the repo at full resolution, so
nothing needed regenerating — IDLE_TARGET_H went to 224 and every sheet was
re-sliced. The sheet-to-output mapping was never recorded, so it was recovered
by matching sliced frames to existing assets by image signature: 58 came back
from sheets, the 29 without a confident match were 2x-upscaled to stay on the
shared scale, since a sprite off that scale renders at half height.

Tennis untouched: 50 hits / 0 whiffs. 45-game soak clean, all four chapters.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 16:23:04 +02:00
wuwiandClaude Fable 5 69e3a0c310 Zombie town: the match continues
Win your first game and the applause cuts off mid-clap. The palette drains,
the umpire lowers his voice ('Quiet... please'), your opponent turns — torn
red polo, dragging his racket — and shamblers come over the billboard wall.
The scoreboard rewrites CPU to THEM. 'Play.'

- zombies.js: shamblers walk your way; quality shots splatter them (gore
  decal + particle burst + wet synth splat), weak sitters only stagger them
  back; one crossing your baseline is a point for THEM
- tennis scoring machinery keeps running untouched: fifteen, thirty, deuce,
  and 'Game, set... massacre' on a game win, all in recorded umpire English
- ball boys mop the gore they pass (their destiny fulfilled)
- transition: palette lerp, scripted spawns incl. the turned opponent,
  new recorded lines (quiet_dark, remain_seated, play, new_balls)
- moan ambience, drained splatter palette, all zombie params in TUNE

Verified: transition triggers on first game win, splat/stagger/baseline
scoring all correct, dead-ball flow feeds fresh serves, tennis mode
regression clean (6/6 returns, 6/6 points resolved).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 16:26:49 +02:00