The flick shows itself, the width is a dial, the blood stays on
Three asks. The placement ring: an aimed rally hit stamps a gold ring that fades where the shot is going — flick, watch it bite the corner, learn the cause. Not stamped for unaimed hits (marking scatter would teach noise), gone in 0.8s (a permanent ring reads as a target rather than feedback). The opponent's width is the ladder's third dial. Its returns scatter off aimError x (1 - quality), which painted lines from game one. matchWideBase 2.1 keeps opponent one inside what an auto-run player can cover — measured, 25 returns all inside +-2.2m — and matchWidePer earns 0.4m per rung, so line-painting is the late ladder. Speed, reliability, width: three dials. The blood vignette replaces the temporary border. The old wash flashed 0.3s and vanished, so between hits the screen said you were fine. A radial vignette reads G.hp directly now — its depth is your damage fraction, permanent until healed, hit pulse riding on top. Global: the hp channel is global. Same no-HP-bar philosophy one layer out; at 1 hp the frame is properly blood-rimmed and the court centre stays legible. 44 tests, 12 seeds clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d6df582cd4
commit
8ccf0a8fad
7 files changed
+81
-9
No files matched your search
+24
-7
@@ -1727,6 +1727,13 @@ export function render() {
|
||||
}
|
||||
drawPiles(false); // far-side piles (occluded by the net); near-side piles drawn after the net
|
||||
|
||||
// THE PLACEMENT RING (match): where your aimed rally shot is going, drawn the moment you flick.
|
||||
// Gold, fading over 0.8 s — flick, watch the ring bite the corner, learn what the gesture does.
|
||||
if (G.placeMark) {
|
||||
ctx.globalAlpha = Math.min(1, G.placeMark.t / 0.5);
|
||||
drawRing(G.placeMark.x, G.placeMark.z, UI.warm, 0.9);
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
// landing ring: white = incoming ball (a PREDICTION, gone the moment the ball touches down —
|
||||
// the ring that lingered where the ball had already landed confused testers and is removed)
|
||||
if (G.phase === 'rally' && ball.active && ball.bounces === 0 && ball.lastHit === 'O') {
|
||||
@@ -1954,13 +1961,23 @@ export function render() {
|
||||
// bomb bloom: a warm blood-orange wash, not a white-out. At 0.85 white it blinded you on a phone
|
||||
// and hid the very gore eruption it was announcing.
|
||||
if (G.boomFlash > 0) { ctx.fillStyle = `rgba(255,150,70,${Math.min(1, G.boomFlash / 0.06) * 0.3})`; ctx.fillRect(0, 0, W, H); }
|
||||
// took a ranged hit: a red wash from the screen EDGES inward. Deliberately not a full-screen fill —
|
||||
// this channel must read as "you are bleeding", not as "something exploded" (that is boomFlash).
|
||||
if (G.hurtFlash > 0) {
|
||||
const a = Math.min(1, G.hurtFlash / 0.3) * 0.55, b = 26;
|
||||
ctx.fillStyle = `rgba(150,10,14,${a.toFixed(3)})`;
|
||||
ctx.fillRect(0, 0, W, b); ctx.fillRect(0, H - b, W, b);
|
||||
ctx.fillRect(0, 0, b, H); ctx.fillRect(W - b, 0, b, H);
|
||||
// THE BLOOD VIGNETTE — the hp channel, worn permanently. The old edge wash flashed for a third
|
||||
// of a second and vanished, so between hits the screen said you were fine; Oliver asked for the
|
||||
// opposite: "a blood red vignette which gets worse with every hit". It reads G.hp directly — a
|
||||
// radial darkening of the frame's edges whose depth IS your damage fraction — and the hit itself
|
||||
// rides on top as a brief brighter pulse (hurtFlash, kept). No HP bar anywhere, still: the
|
||||
// vignette is the same drawn-on-the-man philosophy, one layer out.
|
||||
{
|
||||
const dmg = 1 - Math.max(0, G.hp) / (G.hpMax || 1);
|
||||
const pulse = G.hurtFlash > 0 ? Math.min(1, G.hurtFlash / 0.3) * 0.3 : 0;
|
||||
if (dmg > 0 || pulse > 0) {
|
||||
const a = Math.min(0.72, dmg * 0.5 + pulse);
|
||||
const g = ctx.createRadialGradient(W / 2, H / 2, Math.min(W, H) * (0.52 - dmg * 0.14),
|
||||
W / 2, H / 2, Math.max(W, H) * 0.74);
|
||||
g.addColorStop(0, 'rgba(120,8,12,0)');
|
||||
g.addColorStop(1, `rgba(120,8,12,${a.toFixed(3)})`);
|
||||
ctx.fillStyle = g; ctx.fillRect(0, 0, W, H);
|
||||
}
|
||||
}
|
||||
|
||||
// HUD — Wimbledon manual scoreboard as a 16-bit panel: bevelled bottle-green box (light
|
||||
|
||||
Reference in new issue
Block a user