The flick aims relative to the player: a full sweep from where you stand, not from the court's centre

Third round of the flick report, and this was the core all along: 'when
the opponent and the player are both standing in the left service box it
is virtually impossible to flick the ball into the left out. no matter
how hard/good I flick.' The lane was absolute — a full flick asked for
flickWidth off the court's CENTRE — so the gesture saturated near a
sideline: from x -2 a perfect left flick moved the ball under 2 m and
could never pass the line, and the better the timing the firmer the cap,
because scatter was the only thing that could cross it. 'Left is
impossible, right works' was never left-vs-right: it was
toward-the-near-sideline vs across-the-court.

TUNE.aimAnchor: the anchor slides from the court centre to the player's
own x as the swipe commits (ch.x * |sway| * aimAnchor), so a flat tap is
exactly what it always was and a full flick is a full sweep from where
you stand — including past the line. Out-by-aim is a choice now, per
Oliver's explicit direction; the placement ring already turns red for
it. 0 restores the absolute lane, blendable live in the panel. Player
rally lanes only; the opponent's lanes and the centre-stated pOut
invariants are untouched. Verified in his exact scene: full left flick
from the left box lands -5 (the alley), half swipe -3.07, full right
+1.93.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Fable 5 committed 2026-08-20 14:25:24 +02:00
1 parent 60127436a0
commit 7e5c3ab399
5 files changed
+75 -2

No files matched your search

+34
View File
@@ -876,6 +876,40 @@ test('an aimed shot keeps its DIRECTION: scatter may push it wider, never back p
'aimTrust*aimError must stay under a committed swipe\'s worst-case aim');
});
test('the flick aims RELATIVE TO THE PLAYER: a full sweep from where you stand, not from centre', () => {
// Third round of the service-line report: the lane was absolute, so standing near a sideline
// saturated the gesture — from the left box a perfect left flick moved the ball under 2 m and
// could never find the line ("no matter how hard/good I flick"). The anchor follows the player
// as the swipe commits (TUNE.aimAnchor); a flat tap keeps its old centre default.
startMatch();
G.modal = null; G.modalQ.length = 0;
const arm = (px, swipe) => { // one rally ball, contact at the window's centre
G.interlude.introT = 0; G.phase = 'rally';
P.x = px; P.z = 22.8; P.swingT = -1; G.placeMark = null;
ball.active = true; ball.lastHit = 'O'; ball.bounces = 1;
ball.x = px; ball.y = 0.7; ball.z = P.z - 4.15;
ball.vx = 0; ball.vy = 2.0; ball.vz = 14; ball.g = TUNE.gravity;
G.swipe = swipe;
keyPressed('Space');
for (let i = 0; i < 30 && ball.lastHit !== 'P'; i++) update(DT);
assert.equal(ball.lastHit, 'P', 'contact happened');
G.swipe = null;
return G.placeMark;
};
const full = fx => ({ ax: Math.sign(fx), az: 0, fx, fy: 0, mag: TUNE.flickFull });
const line = COURT.W / 2;
// from the LEFT service box, a committed left flick reaches PAST the line — out is aimable now
const left = arm(-2, full(-1));
assert.ok(left && left.x < -line, 'full left flick from the left box finds the alley: x=' + left.x.toFixed(2));
// ...and a right flick from the same spot lands a full sweep right OF THE PLAYER, near centre-right
const right = arm(-2, full(1));
assert.ok(right && right.x > 1.2 && right.x < 2.8, 'full right flick sweeps from the player: x=' + right.x.toFixed(2));
// an unaimed tap is untouched by where you stand: no mark, and the ball heads for the centre
assert.equal(arm(-2, null), null, 'a flat tap from the box stamps no mark, exactly as before');
assert.ok(Math.abs(ball.vx * ((3 - ball.z) / ball.vz) + ball.x) < TUNE.aimError + 1,
'and its line stays the old centre default, not the player lane');
});
test('the flick aims from the LIVE swipe: contact reads G.swipe, no release needed', () => {
// The swing fires the moment the drag crosses flickMin now (input.js), so at contact the finger
// is usually still down and no released flickAim exists yet. The aim has to come from the live