Aim the ball at the chest, and stop lobbing at a net that isn't there
THE BALL WAS SOLVED TO THE GROUND. solveShot's terminal height was a hardcoded 0.08 — ball-on-the-grass — so a splatter serve came down past the shambler and registered at the ankles however the mark was drawn. It now takes an arrival height, and a lane shot aims at the body: zombieH x Z_CHEST, scaled off the same height table render draws with, so a brute is struck on the brute rather than at the height a shambler's chest happens to be. Measured at the frame the wound registers: shambler 1.11 m of 1.8, brute 1.64 m of 2.7, and an empty lane still lands on the grass. The aim mark reads the same `ty`, so mark, arc end and impact are now one point instead of three guesses. AND A BUG FOUND ON THE WAY. The net-clearing loop ran for shots that never reach the net. A shambler on your own side sits short of the tape, so `tN` is still positive — the net is ahead in the direction of travel, the ball simply lands first — the height test there is far below the tape, and the loop spent all twelve cuts. Every same-side shot left the racket at 28% of nominal pace as a slow loop. That is exactly the shot that needs to be fast: those are the ones about to eat you. Guarded on the shot actually crossing the net, in serveArc and in doHit's copy. Flight time to a body at z=16 drops 0.71 s -> 0.20 s. THIS ONE IS A FEEL CHANGE YOU DID NOT ASK FOR — near shots are now fast and flat where they used to loop. Say if you want the lob back. Tennis and the duel still serve into the box, far-side shots still clear the tape, 900 frames of splatter render clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ff9e09e3eb
commit
2edabe6c64
3 files changed
+52
-23
No files matched your search
@@ -1,7 +1,7 @@
|
||||
// Camera, viewport, sprites and all drawing. Owns the crowd dots (visual-only state).
|
||||
|
||||
import { cv, ctx } from './dom.js';
|
||||
import { TUNE, UI, EATEN_GRAB, EATEN_BURST, EATEN_SUMMARY, EATEN_RESTART, COURT, P_BOUNDS, PLAYER_H, BOY_H, UMP_H, UMP_X, MACH_H, BOSS_ART, BOUNCE_IDLE, SPRITE_H } from './config.js';
|
||||
import { TUNE, UI, EATEN_GRAB, EATEN_BURST, EATEN_SUMMARY, EATEN_RESTART, COURT, P_BOUNDS, PLAYER_H, BOY_H, UMP_H, UMP_X, MACH_H, BOSS_ART, BOUNCE_IDLE, SPRITE_H, zombieH } from './config.js';
|
||||
import { P, O, ball, score, crowd, G, court } from './state.js';
|
||||
import { predictLanding, previewServe } from './gameplay.js';
|
||||
import { zombies, gore, piles, parts, pellets, extras, shots } from './zombies.js';
|
||||
@@ -354,8 +354,10 @@ function drawZombie(zb) {
|
||||
const chairDown = zb.variant === 's' && zb.shieldT > 0; // chair dropped — hit it NOW. Its own sprite
|
||||
// now (z_sdown); it used to be walk frame 3,
|
||||
// which a 4-frame cycle would walk right through
|
||||
let h = zb.variant === 'g' ? 2.7 : zb.variant === 'd' ? 2.15 : rk ? 1.85 : 1.8; // the brute towers half again over the crowd; the steward stands between him and it
|
||||
if (zb.variant === 'B') h = 1.8 * (zb.scale || 1.5); // ...and a chapter boss towers over the brute
|
||||
// the brute towers half again over the crowd, the steward stands between him and it, and a
|
||||
// chapter boss towers over the brute. Shared with gameplay, which aims the serve at a fraction
|
||||
// of this — if the two tables drifted the ball would arrive at the wrong part of the body.
|
||||
let h = zombieH(zb); // NOT const: the headless boss skin shortens it, and the sprite sheet scales it
|
||||
// wounded skins: multi-hit enemies show their damage as hp drops (arm off → head gone, still
|
||||
// shambling). The blood is NOT painted in — open wounds gush live particles (see bleed() in
|
||||
// zombies.js). Fall back to the healthy sprite until the wounded PNG has loaded.
|
||||
@@ -502,7 +504,7 @@ function drawAimMark(a, u0) {
|
||||
if (left <= 0.01) return;
|
||||
const col = a.q >= TUNE.zSplatQ ? (a.zt ? UI.hot : UI.warm) : '#9db4d0';
|
||||
const onBody = !!a.zt;
|
||||
const m = proj(a.tx, onBody ? 0.95 : 0, a.tz);
|
||||
const m = proj(a.tx, a.ty, a.tz); // a.ty is where the ball ARRIVES — mark and impact are one point
|
||||
ctx.globalAlpha = (onBody ? 0.42 : 0.24) * left;
|
||||
ctx.fillStyle = col;
|
||||
ctx.beginPath();
|
||||
|
||||
Reference in new issue
Block a user