A gesture is read in a pause, not in a point
The flick lesson rode the incoming ball, over the player's shoulder — the one moment he has no attention to spare for reading anything. It moves into the room this game already keeps for teaching gestures: the serve stance, standing still, mimed on the apron by the very demo the slingshot lesson plays. Same clock, same hand, same words slot — one teacher, three lessons, and nothing new drawn over a live rally. The words carry both halves now, SWIPE AS YOU HIT TO AIM: WHEN alone teaches nothing, and WHAT FOR alone gets tried at the wrong moment and read as a gesture that does not work. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
67cb0b74d7
commit
553b765846
3 files changed
+35
-31
No files matched your search
+7
-2
@@ -91,8 +91,13 @@ communicating its own rules. Model A only works if the player can see they are b
|
|||||||
only way in.
|
only way in.
|
||||||
|
|
||||||
6. ~~**Teaching**~~ **DONE** (2026-08-17). The ghost-hand lesson for the PLACEMENT FLICK, in the
|
6. ~~**Teaching**~~ **DONE** (2026-08-17). The ghost-hand lesson for the PLACEMENT FLICK, in the
|
||||||
same register as PULL DOWN and TAP AS IT ARRIVES: a dotted track out of the player, the hand
|
same register as PULL DOWN and SWIPE TO DODGE — because it is now literally the same demo: the
|
||||||
riding it, SWIPE AS YOU HIT, mimed both ways in turn so it never teaches one corner.
|
apron mime, played in the SERVE STANCE after a beat of standing still, mimed both ways in turn so
|
||||||
|
it never teaches one corner. **A gesture is read in a pause, not in a point** (Oliver: "it is
|
||||||
|
displayed mid-play.. please rather show it in one of the pauses"): the first cut rode the
|
||||||
|
incoming ball, over the shoulder, at the moment the player has the least attention to spare.
|
||||||
|
The words carry both halves — SWIPE AS YOU HIT TO AIM — because WHEN alone teaches nothing and
|
||||||
|
WHAT FOR alone gets tried at the wrong moment and read as broken.
|
||||||
It rides the failure it answers — `G.flatStreak`, returns that left with no aim on them
|
It rides the failure it answers — `G.flatStreak`, returns that left with no aim on them
|
||||||
(`flatCount`, reset by the first aimed one) — and only after `TUNE.flickHintAfter` of them,
|
(`flatCount`, reset by the first aimed one) — and only after `TUNE.flickHintAfter` of them,
|
||||||
because hitting flat is a legal shot and not a mistake. **One lesson at a time:** the tap hint
|
because hitting flat is a legal shot and not a mistake. **One lesson at a time:** the tap hint
|
||||||
|
|||||||
+1
-1
@@ -659,6 +659,6 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="module" src="src/main.js?v=279"></script>
|
<script type="module" src="src/main.js?v=280"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
+27
-28
@@ -2140,26 +2140,22 @@ function drawHitHint() {
|
|||||||
// goes, and wrong-footing the body across the net is how points are actually won. It was taught
|
// goes, and wrong-footing the body across the net is how points are actually won. It was taught
|
||||||
// nowhere on touch: the placement ring shows the result of a flick, which is a receipt, not a
|
// nowhere on touch: the placement ring shows the result of a flick, which is a receipt, not a
|
||||||
// lesson — if you never happen to swipe you never get one, so you never learn there was anything
|
// lesson — if you never happen to swipe you never get one, so you never learn there was anything
|
||||||
// to learn. Same ghost hand as every other gesture in this game, over the same shoulder, riding
|
// to learn.
|
||||||
// the same failure it answers (a run of returns hit flat — doHit resets flatStreak the moment one
|
// IT IS TAUGHT IN THE PAUSE, NOT IN THE POINT. It first rode the incoming ball, over the player's
|
||||||
// leaves with an aim on it). It mimes BOTH ways in turn or it teaches one corner.
|
// shoulder — which is the moment he has the least attention to spare for reading anything: "it is
|
||||||
|
// displayed mid-play.. please rather show it in one of the pauses" (Oliver, 2026-08-17). So it
|
||||||
|
// moved into the room this game already keeps for teaching gestures: standing still in the serve
|
||||||
|
// stance, on the apron, in the very demo the slingshot lesson plays. Same clock, same mime, same
|
||||||
|
// words slot — one teacher, three lessons, and nothing new drawn over live play.
|
||||||
|
// Both ways in turn, or it teaches one corner, and away from whichever edge he is standing against.
|
||||||
function drawFlickHint() {
|
function drawFlickHint() {
|
||||||
const cyc = 1.4, t = G.idleT % cyc;
|
const n = ((G.idleHintT - TUNE.pullHintAfter) / 1.9) | 0;
|
||||||
const dir = (((G.idleT / cyc) | 0) % 2) ? -1 : 1;
|
const px = proj(P.x, 0, P.z).x;
|
||||||
const slide = Math.min(1, t / 0.8), gone = t > 0.95; // stroke, held a beat, lifted, repeat
|
// ...and the words carry BOTH halves, because either one alone is useless: WHEN (as you hit —
|
||||||
if (gone) return;
|
// a swipe at any other moment does nothing, and a player who tries one and sees nothing concludes
|
||||||
const p0 = proj(P.x, 0, P.z);
|
// the gesture is not there) and WHAT FOR (it aims). One line, the same imperative as PULL DOWN
|
||||||
const hx = Math.round(p0.x), hy = Math.round(p0.y) - 52;
|
// and TAP AS IT ARRIVES.
|
||||||
ctx.save(); ctx.globalAlpha = 0.9;
|
demoSwipe(px < W * 0.3 ? 1 : px > W * 0.7 ? -1 : (n % 2 ? -1 : 1), 0, 'SWIPE AS YOU HIT TO AIM');
|
||||||
ctx.fillStyle = UI.dim; // the track the thumb travels
|
|
||||||
for (let d = 10; d <= 38; d += 7) ctx.fillRect(hx + dir * d - 1, hy, 2, 2);
|
|
||||||
drawGhostHand(hx + dir * (10 + 28 * slide), hy, 1); // starts clear of his own sprite
|
|
||||||
ctx.font = F(10); ctx.textAlign = 'center'; ctx.textBaseline = 'top';
|
|
||||||
// ...and the words sit ABOVE the stroke and OPPOSITE it: below is the player's own feet and the
|
|
||||||
// BASELINE, and 10px type across a bright white line is the one place on this court it cannot be
|
|
||||||
// read. Clamped off the screen edges too — this rides the player and he stands in the corners.
|
|
||||||
shadowText('SWIPE AS YOU HIT', Math.max(52, Math.min(W - 52, hx - dir * 22)), hy - 26, UI.warm);
|
|
||||||
ctx.restore();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The modal: drawn LAST, over everything, and the world behind it is frozen (gameplay.update
|
// The modal: drawn LAST, over everything, and the world behind it is frozen (gameplay.update
|
||||||
@@ -2729,19 +2725,22 @@ export function render() {
|
|||||||
if (txt) shadowText(txt, W / 2, METER_Y(), UI.warm); // same slot the draw meter uses
|
if (txt) shadowText(txt, W / 2, METER_Y(), UI.warm); // same slot the draw meter uses
|
||||||
if (demo) drawPullHint(); // show the gesture instead of only naming it
|
if (demo) drawPullHint(); // show the gesture instead of only naming it
|
||||||
}
|
}
|
||||||
// the tennis struggle hints: both ride the exact failure they answer, and only one at a time —
|
// the tennis struggle hints, each riding the exact failure it answers.
|
||||||
// teaching the flick to someone who cannot get a racket on the ball is the wrong lesson, so the
|
// The TAP lesson stays on the incoming ball: it is about a moment, and a moment can only be
|
||||||
// tap always wins.
|
// taught while it is happening. The FLICK lesson is about a gesture, and a gesture is read in a
|
||||||
// THE FLICK LESSON BELONGS TO THE RALLY MODES, which is what rallyFeel() already means: CLASSIC
|
// PAUSE — so it waits for the serve stance and mimes itself on the apron there, exactly like the
|
||||||
// and ZOMBIE TENNIS. Not the gore mode, and not gore's OPENER either — that tennis is a prologue
|
// slingshot's. Nothing new is drawn over a live rally.
|
||||||
// you play for one game before the court turns, and placement is not the skill it is asking for.
|
// It belongs to the RALLY MODES, which is what rallyFeel() already means: CLASSIC and ZOMBIE
|
||||||
|
// TENNIS. Not the gore mode, and not gore's OPENER either — that tennis is a prologue you play
|
||||||
|
// for one game before the court turns, and placement is not the skill it is asking for.
|
||||||
// (`G.mode === 'tennis'` covered classic AND that prologue, which is exactly the wrong seam; the
|
// (`G.mode === 'tennis'` covered classic AND that prologue, which is exactly the wrong seam; the
|
||||||
// match itself is not mode 'tennis' at all, it plays under splatter's permanent interlude.)
|
// match itself is not mode 'tennis' at all, it plays under splatter's permanent interlude.)
|
||||||
// Touch only: on a keyboard the aim is held keys and 'SWIPE' would name a gesture that does not
|
// Touch only: on a keyboard the aim is held keys and 'SWIPE' would name a gesture that does not
|
||||||
// exist there.
|
// exist there.
|
||||||
const inRally = G.phase === 'rally' && ball.active && ball.lastHit === 'O';
|
if (G.mode === 'tennis' && G.phase === 'rally' && G.passStreak >= 2 && ball.active && ball.lastHit === 'O')
|
||||||
if (G.mode === 'tennis' && inRally && G.passStreak >= 2) drawHitHint();
|
drawHitHint();
|
||||||
else if (IS_TOUCH && inRally && rallyFeel() && G.flatStreak >= TUNE.flickHintAfter)
|
else if (IS_TOUCH && rallyFeel() && G.phase === 'pretoss' && G.idleHintT > TUNE.pullHintAfter
|
||||||
|
&& G.flatStreak >= TUNE.flickHintAfter)
|
||||||
drawFlickHint();
|
drawFlickHint();
|
||||||
// The free-floating register: no panel, one fixed slot, shouted. PERFECT, GAME N, DOUBLE KILL,
|
// The free-floating register: no panel, one fixed slot, shouted. PERFECT, GAME N, DOUBLE KILL,
|
||||||
// RETURNED, CHANGEOVER, weapon labels — everything that used to be plain white 12px text sitting
|
// RETURNED, CHANGEOVER, weapon labels — everything that used to be plain white 12px text sitting
|
||||||
|
|||||||
Reference in new issue
Block a user