Shape the cone by hand, and give the playground its knobs back
Oliver's tuned numbers become the defaults: beamY 0.95, beamLen 23, beamW0 0.08, beamW1 3.1, beamOriginLift 0.44, beamBorder 0.18. Three knobs earned their keep on the way there. beamLen is the DRAWN length now, not only the kill range. The drawn length was solved every frame so the far end landed on the middle of the ad strip, which made this a control that visibly did nothing. One meaning beats one clever behaviour -- and it pairs with beamY, since a lower plane meets the ads sooner. beamOriginLift replaces beamOriginY: the apex is a lift ABOVE the plane rather than an absolute height, so lowering beamY brings the near end down with it instead of leaving it hanging at chest height with the beam sloping away. beamBorder exposes the edge width, which was hardcoded. And the playground is back, deliberately NOT paused. The first version froze the world so the picture would hold still, and then nothing redrew, so every value changed did nothing -- a still frame you cannot change is worth nothing. The bodies are held still individually and spawning is off instead. Also: a boolean living in TUNE has to be tested with >= 0.5. The panel steps every key by 0.02, so one nudge set beamBand to 0.02 -- still truthy -- and the renderer switched variants under him mid-tune. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ac1d5fbccd
commit
99774ab4be
6 files changed
+125
-62
No files matched your search
@@ -200,9 +200,48 @@ cv.addEventListener('pointerdown', e => {
|
||||
});
|
||||
|
||||
|
||||
|
||||
// ---- A POSED SCENE for tuning a shot: `T.laserScene()`, or load with #laser. Six bodies of
|
||||
// different types at known depths, the laser armed, a pull held.
|
||||
// IT DOES NOT PAUSE, deliberately. The first version froze the world so the picture would hold
|
||||
// still — and then every TUNE value you changed did nothing visible, because nothing redrew. The
|
||||
// bodies are held still individually (v = 0) and spawning is off instead, so the picture is stable
|
||||
// while the render loop keeps running and an edit shows on the very next frame.
|
||||
function laserScene() {
|
||||
const intro = document.getElementById('intro');
|
||||
if (intro) intro.hidden = true;
|
||||
paused = false;
|
||||
if (G.mode === 'tennis') forceZombies();
|
||||
for (let i = 0; i < 600; i++) update(1 / 60); // ride the transition out into splatter
|
||||
G.modal = null; G.horde = null; G.interlude = false; G.changeover = 0; G.clearing = false;
|
||||
G.mgT = 0; G.gunId = null; G.beam = null; G.bossFight = 0; G.hp = G.hpMax = TUNE.playerHp;
|
||||
zombies.length = 0; pellets.length = 0; parts.length = 0; gore.length = 0; piles.length = 0;
|
||||
score.server = 'P'; setupPoint();
|
||||
P.x = 0;
|
||||
TUNE.zMax = 0; // nothing new wanders into the shot
|
||||
for (const [x, z, v] of [[0, 20, 'a'], [0.75, 16, 'b'], [-0.85, 12, 'k'],
|
||||
[0.85, 8.5, 'g'], [-0.75, 5.5, 'h'], [0, 3, 'e']]) {
|
||||
spawnZombie(x, z, v);
|
||||
zombies[zombies.length - 1].v = 0; // held still: the scene is a photograph
|
||||
}
|
||||
G.rack.length = 0; G.temp = null;
|
||||
G.weapon = grantWeapon('laser');
|
||||
G.modal = null;
|
||||
G.aim = { fx: 0, fy: -1, mag: 100 }; // a full pull straight up-court (fy is NEGATIVE)
|
||||
return 'posed and LIVE — change TUNE (T panel or console) and it redraws. T.laserFire() to shoot it.';
|
||||
}
|
||||
// fire the posed shot, then pose it again so you can keep tuning
|
||||
function laserFire() {
|
||||
G.aim = null; score.server = 'P'; setupPoint();
|
||||
keyPressed('Space');
|
||||
return 'fired — T.laserScene() to re-pose';
|
||||
}
|
||||
// a plain timer, not the load event: this module runs as a module, so `load` may already have gone
|
||||
if (location.hash === '#laser') setTimeout(laserScene, 600);
|
||||
|
||||
requestAnimationFrame(frame);
|
||||
|
||||
// exposed for in-browser sanity checks and simulated playtests
|
||||
window.T = { TUNE, ball, P, O, score, G, zombies, pause: v => { paused = v !== false; }, spawnZombie, spawnRacketZombie, spawnMachine, spawnChapterBoss, spawnBarrel, grantWeapon, toggleTestMode, piles, gore, parts, pellets, extras, shots, explode, hurtPlayer, killPlayer, splatPoint, solveShot, inServeBox, inCourt, proj, setupPoint, forceZombies, deliverTin, selectWeapon, showModal, dismissModal, startDuel, resolveInterlude, flickTarget, startBossFight, endBossFight,
|
||||
window.T = { TUNE, ball, P, O, score, G, zombies, laserScene, laserFire, pause: v => { paused = v !== false; }, spawnZombie, spawnRacketZombie, spawnMachine, spawnChapterBoss, spawnBarrel, grantWeapon, toggleTestMode, piles, gore, parts, pellets, extras, shots, explode, hurtPlayer, killPlayer, splatPoint, solveShot, inServeBox, inCourt, proj, setupPoint, forceZombies, deliverTin, selectWeapon, showModal, dismissModal, startDuel, resolveInterlude, flickTarget, startBossFight, endBossFight,
|
||||
step: dt => update(dt), render, press: keyPressed,
|
||||
get phase() { return G.phase; }, set phase(v) { G.phase = v; } };
|
||||
Reference in new issue
Block a user