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:
1 parent
60127436a0
commit
7e5c3ab399
5 files changed
+75
-2
No files matched your search
@@ -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
|
||||
|
||||
Reference in new issue
Block a user