The opponents come back to life: the friendly refresh, open string beds, and a steadier chase
Oliver's batch, delivered in dependency order. "The opponents look pretty harsh, almost already pre-zombie" — so BOTH tennis opponents got a new identity: warm skin, human eyes, an easy near-smile, rolled anchor-first so every later sheet inherits the face. The male's bounce pair also ADOPTS the female's palm-out posture (his old crouched receiver stance was the wrong pose for bouncing a ball — her better one is now the shared convention), and the pre-serve ball was re-measured onto the drawn palms: BOUNCE_IDLE's oDx 0.45 -> 0.24 / oApex 0.55 -> 0.72 for his close carry, with her wider reach riding TOURS (oDx 0.48 / oApex 0.73) the same way the player's pair already does. "parts of the body as well as the inner of the racket are solid" — the beds were the cutter's own doing: _fine.key repaints enclosed magenta pale grey (protection against accidental magenta strings), which defeated the beds we now draw magenta ON PURPOSE. key()/main() grow a bed=True switch (the famroll convention, used by _runroll and the refresh cuts); the run cycles' beds went from ~70% to ~44% opaque — strings, not paddles. Enclosed pockets of a roll's off-spec background (one sheet came back on blue) are scrubbed by corner-colour distance too. Both RUN CYCLES re-rolled off the friendly anchors: his landed 8 clean frames (racket +0.05..+0.30, one side); hers took four rolls — the gates caught a white background, a crossing racket, near-dup neighbours — and the keeper drew a 10-frame cycle, from which the best 8 were chosen by maximising the minimum adjacent stride (29.7%, smoother than his 22.7). o_run7/8 return to the SPR list. AND THE CHASE STOPS DITHERING (Oliver: "switching between a left and right movement increasingly faster the nearer the ball comes"): intercept() re-solves every frame and the earliest-reachable point jumps around its solution as the flight shortens, flipping his run direction each time. The CPU now commits to its stored target unless a fresh solve moves it by more than 0.35 m. SPRV 121, main.js v244, 66 tests, every opponent frame verified 200 in the live game. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dd8dbd04e9
commit
80bf6c4cee
41 files changed
+37
-14
No files matched your search
+10
-3
@@ -17,7 +17,7 @@ KEY_D2 = 60 * 60
|
||||
MIN_GAP = 12
|
||||
MIN_BLOB = 60
|
||||
|
||||
def key(im, defringe=2):
|
||||
def key(im, defringe=2, bed=False):
|
||||
a = np.array(im.convert('RGBA'))
|
||||
bg = a[0, 0, :3].astype(int)
|
||||
d = ((a[..., :3].astype(int) - bg) ** 2).sum(2)
|
||||
@@ -39,7 +39,14 @@ def key(im, defringe=2):
|
||||
# ...and what that leaves — magenta INSIDE a body — is repainted as pale grey rather than kept,
|
||||
# because bright pink strings are as wrong as no strings. Luminance is preserved, so the drawn
|
||||
# crosshatch survives as crosshatch; only the hue goes.
|
||||
# UNLESS the sheet MEANS its magenta beds (`bed=True` — the famroll convention, adopted by the
|
||||
# opponent refresh and _runroll): then enclosed magenta is the string bed and CUTS TO
|
||||
# TRANSPARENCY, exactly as _zsheet already treats it. The grey repaint is what shipped the
|
||||
# opponents holding solid white paddles.
|
||||
inner = magenta & ~outside
|
||||
if bed:
|
||||
a[inner] = 0
|
||||
inner = np.zeros_like(inner)
|
||||
if inner.any():
|
||||
lum = a[..., :3].mean(2)
|
||||
a[inner, 0] = a[inner, 1] = a[inner, 2] = np.clip(lum[inner] * 0.5 + 115, 0, 255).astype('uint8')
|
||||
@@ -152,8 +159,8 @@ def frames(a, cuts, want=0):
|
||||
out = list(zip(edges, edges[1:]))
|
||||
return out
|
||||
|
||||
def main(sheet, outs, target_h, cuts, anchor, defringe=2):
|
||||
a = key(Image.open(sheet), defringe)
|
||||
def main(sheet, outs, target_h, cuts, anchor, defringe=2, bed=False):
|
||||
a = key(Image.open(sheet), defringe, bed)
|
||||
b = block_size(a)
|
||||
crops = []
|
||||
spans = frames(a, cuts, len(outs))
|
||||
|
||||
Reference in new issue
Block a user