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:
1 parent
f6dfc57a06
commit
6378ff2a1b
11 files changed
+30
-97
No files matched your search
@@ -91,19 +91,6 @@ def touches_edge(sheet):
|
||||
return best
|
||||
return max(run(fg[0]), run(fg[-1]), run(fg[:, 0]), run(fg[:, -1])) >= 8
|
||||
|
||||
def arm_not_left(outs):
|
||||
"""The generator MIRRORS the later frames of a serve about half the time — the coil is a strong
|
||||
silhouette and it draws it whichever way it likes, which puts the racket in the other hand
|
||||
halfway through the animation. Oliver spotted it twice. Every frame after the first must reach
|
||||
its raised arm up the LEFT-hand side, so a frame whose left half has nothing near the top (the
|
||||
arm went right instead) is a rejected roll, not something to notice later in the file browser."""
|
||||
for o in outs[1:]:
|
||||
ink = np.array(Image.open(o).convert('RGBA'))[..., 3] > 128
|
||||
h, w = ink.shape
|
||||
left = np.nonzero(ink[:, :w // 2].any(1))[0]
|
||||
if not len(left) or left.min() > 0.18 * h: return o
|
||||
return None
|
||||
|
||||
def colour_match(src, dst_name):
|
||||
"""Fit the new frame onto the palette statistics of the sprite it replaces, so a redrawn body
|
||||
does not change colour halfway through a walk cycle."""
|
||||
@@ -146,10 +133,6 @@ def run(name, spec, dry=False):
|
||||
print(r.stdout.strip() or r.stderr.strip())
|
||||
if r.returncode or not all(os.path.exists(o) for o in outs):
|
||||
print(f'[{name}] REJECTED: slicing failed (frames merged?) — re-run or add "cut"'); return False
|
||||
if spec.get('arm_left'):
|
||||
bad = arm_not_left(outs)
|
||||
if bad:
|
||||
print(f'[{name}] REJECTED: {bad} was drawn MIRRORED — racket in the wrong hand'); return False
|
||||
if lead: outs = outs[1:] # the scale reference is not installed
|
||||
before = [density(os.path.join(HERE, s + '.png')) for s in sprites]
|
||||
after = [density(o) for o in outs]
|
||||
|
||||
Reference in new issue
Block a user