Synthwave verges stay off the road; camera stays level unless the tail says otherwise
Synthwave Run: roadside passers stream on the verges, not on the road. Each passer places at roadHalf + psize*0.92 + gap where roadHalf mirrors the grid's abs(p.x*perspective) < 0.8, so even a large chorus form's edge stays clear of the centre lane reserved for the protagonist. Lateral wobble reduced to worst ~0.025 inward vs. minimum 0.07 gap so it can never carry back onto the road. Four random chorus objects rushing horizon->camera make each song's traffic its own; on-road traffic the hero weaves around is left as a separate kind later. Also carries the previous chorus passer loop, hero castSolid, and texture 0.4 / form+staging declarations still pending in the working tree from the last step. Personality camera: uniform boxes put as many tracks at the wild edge as near level, so the grid swung too often. Replace with a bell curve (Box-Muller over the seeded Rng) — mode at level, rarity in the tails. driftRate/sway/swayRate/spin/breathe now via gaussAround(centre,sigma) centred near level (spin at 0, sign from the Gaussian itself) with audio tilting the centre (fast→more drift/sway/spin, dynamic→breathe) rather than displacing the whole box. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,15 @@ export const TRAITS = ['shape', 'camera', 'space', 'style'];
|
||||
|
||||
const clamp01 = (x) => Math.max(0, Math.min(1, x));
|
||||
|
||||
// Box-Muller standard normal from the seeded rng. Two uniform draws per
|
||||
// sample; the mode is at 0 and the tails are rare, which is the whole
|
||||
// point — uniform boxes put as many tracks at the wild edge as near level.
|
||||
function gauss(rng) {
|
||||
const u1 = Math.max(rng.next(), 1e-7);
|
||||
const u2 = rng.next();
|
||||
return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traits eligible to be a track's signature, and how often.
|
||||
*
|
||||
@@ -137,16 +146,29 @@ export function generatePersonality(summary, rng, countEligible = null, sections
|
||||
tilt: rng.range(0, Math.PI),
|
||||
};
|
||||
|
||||
// Camera: bell-curve over level vs. wild. Most tracks stay near
|
||||
// level — a little drift, a little sway, almost no roll — and only
|
||||
// the tail really swings. Uniform boxes put as many tracks at the
|
||||
// wild edge as near level, which is why the grid read as wild so
|
||||
// often; a Gaussian puts the mode at level and rarity in the tails.
|
||||
// Audio still tilts the centre (fast → more drift/sway/spin,
|
||||
// dynamic → more breathe) but the seed picks within a bell around it.
|
||||
const gaussAround = (centre, sigma, lo, hi) =>
|
||||
Math.max(lo, Math.min(hi, centre + gauss(rng) * sigma));
|
||||
const camera = {
|
||||
driftAngle: rng.range(0, Math.PI * 2),
|
||||
// A slow track should not be filmed from a moving car.
|
||||
driftRate: rng.range(0.01, 0.06) * (0.6 + fast * 0.8),
|
||||
sway: around(0.01 + fast * 0.035, 0.02, 0, 0.06),
|
||||
swayRate: around(0.08 + fast * 0.1, 0.06, 0.05, 0.22),
|
||||
spin: around((rng.bool() ? 1 : -1) * fast * 0.03, 0.025, -0.05, 0.05),
|
||||
// A slow track should not be filmed from a moving car. Centre near
|
||||
// level (0.016 + tempo), sigma narrow so wild drift is a tail event.
|
||||
driftRate: gaussAround(0.016 + fast * 0.016, 0.010, 0.004, 0.065),
|
||||
sway: gaussAround(0.010 + fast * 0.018, 0.009, 0, 0.055),
|
||||
swayRate: gaussAround(0.09 + fast * 0.06, 0.028, 0.05, 0.22),
|
||||
// Spin centred at zero — most tracks stay level, only the tails roll.
|
||||
// Spread scales with tempo so a fast track has a wider bell, not a
|
||||
// displaced one. Sign comes from the Gaussian itself.
|
||||
spin: gaussAround(0, 0.012 + fast * 0.012, -0.05, 0.05),
|
||||
// Breathing is locked to the bar, so it is the one camera move that
|
||||
// reads as musical rather than as drifting. A dynamic track breathes.
|
||||
breathe: around(dynamic * 0.03, 0.02, 0, 0.05),
|
||||
breathe: gaussAround(dynamic * 0.022, 0.010, 0, 0.048),
|
||||
};
|
||||
|
||||
const space = {
|
||||
|
||||
Reference in New Issue
Block a user