Make the plane solid, and take the posed scene back out

The cone is fully opaque now: solid colour, deep blue at the edges and near-white
down the core, dimming as it runs away. Depth is carried by BRIGHTNESS instead of
by alpha, so it still reads as receding without anything showing through.

That settles an argument the translucent version could not win. Its opacity and
how well you could tell above-the-plane from below-the-plane were the same dial
pulling opposite ways: readable enough to show the split and it veiled the whole
cone, subtle enough to look right and there was nothing to see. Solid, a body
above the plane is drawn on top of it and a body below is hidden behind it. The
trade is that you cannot see the crowd through it, which is the thing to judge on
the phone.

The `alpha` parameter went with it rather than being left in the signature lying
about what it does.

laserScene is gone. T.pause(true) stays -- it freezes the world but keeps drawing,
which is worth having whenever a still is what you need to look at.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-03 17:21:21 +02:00
1 parent 44419d9ce1
commit 601aa934ad
4 files changed
+43 -81

No files matched your search

+12 -21
View File
@@ -443,11 +443,13 @@ that holds that height all the way out instead of sloping to the ground — that
makes the rest possible. Sloping, it lay flat on the grass across the whole far half, so there was
nothing for it to cut exactly where the crowd stands.
- **The cone's opacity and the over/under read are the SAME dial, and they pull against each other.**
The plane is flat: a body above it is drawn clean on top, a body below is seen THROUGH it — so how
clearly you can tell the two apart just is how opaque the cone is. Oliver asked for a fainter,
bluer cone AND a clearer split; the first wins, and the CUT LINE carries the signal instead. Do not
try to "fix" the split by raising the cone alpha again — that is the thing he asked to come down.
- **THE PLANE IS OPAQUE, and that is what settled it.** While it was translucent, its opacity and
the over/under read were the same dial pulling in opposite directions: readable enough to show the
split and it veiled the whole cone, subtle enough to look right and you could not tell above from
below at all. Solid colour ends the argument — a body above the plane is drawn on top of it, a body
below is simply hidden behind it. **Depth is carried by BRIGHTNESS** (full at the strings, half at
the ads) rather than by alpha, which is why it still reads as receding. `BEAM_EDGE`/`BEAM_MID`/
`BEAM_CORE` are the three colours. The trade is that you cannot see the crowd through it.
- **The fill is TWO gradients**, matching the reference Oliver sent: a horizontal one across the
width (near-white down the centre line, falling to the weapon's blue at the edges) and a depth one
along the length. Canvas has no 2D gradient, so the wedge is filled in eight slices along its
@@ -482,23 +484,12 @@ nothing for it to cut exactly where the crowd stands.
are AIMING rather than only on the shot. Measured on desktop: 0.27 ms/frame with 20 bodies against
a 16.7 ms budget.
## T.laserScene() — a posed, PAUSED scene for looking at a shot
## T.pause(true) — freeze the world, keep drawing
`T.laserScene()` in the console (or load the page with `#laser`) drops you into splatter with six
bodies of different types at known depths, the laser armed, a full pull held, and the world PAUSED.
**`T.pause(true)` freezes the world but keeps DRAWING**, which is the point: change `TUNE.beamY` or a
colour in devtools and the next frame shows it, with the scene standing still. The old test recipe
halted rAF instead (`requestAnimationFrame = () => 0`), which freezes the picture too and is useless
for judging how something looks. `T.pause(false)` runs again; `T.render()` redraws by hand.
It sets `TUNE.zMax = 0` so nothing wanders into the shot — that persists after unpausing, so reload
before playing on.
The knobs worth turning there: `beamY` (the height the plane holds, and the line it cuts bodies at),
`beamOriginY`, `beamRise`, `beamW0`/`beamW1` (half-width at the racket and at the far end), `beamLen`
(the KILL range — the drawn length is solved separately against the ad strip), `beamT`, `dmgBeam`.
The cone's colours are the gradient stops in `drawBeamWedge`; the cut line is `CUT_COL`.
`T.pause(true)` stops `update()` but keeps `render()` running, so a value changed in devtools shows
on the next frame while the scene stands still. The older recipe halted rAF
(`requestAnimationFrame = () => 0`), which freezes the PICTURE too and is no use for judging how
something looks. `T.pause(false)` runs again.
## TEST MODE — triple-tap the scoreboard