diff --git a/party-stage/src/scene/stage-lasers.js b/party-stage/src/scene/stage-lasers.js index cba562c..415e864 100644 --- a/party-stage/src/scene/stage-lasers.js +++ b/party-stage/src/scene/stage-lasers.js @@ -117,10 +117,24 @@ export class StageLasers extends SceneFeature { if (this.activationState === 'IDLE') { // Wait for song to pick up before first activation if (time > this.initialSilenceSeconds && loudness > this.averageLoudness + 0.1) { + this.activationState = 'WARMUP'; + this.stateTimer = 1.0; // Warmup duration + } + } else if (this.activationState === 'WARMUP') { + isActive = true; + this.stateTimer -= deltaTime; + if (this.stateTimer <= 0) { this.activationState = 'ACTIVE'; this.stateTimer = 4.0; // Active duration } } else if (this.activationState === 'ACTIVE') { + isActive = true; + this.stateTimer -= deltaTime; + if (this.stateTimer <= 0) { + this.activationState = 'FADEOUT'; + this.stateTimer = 1.0; // Fadeout duration + } + } else if (this.activationState === 'FADEOUT') { isActive = true; this.stateTimer -= deltaTime; if (this.stateTimer <= 0) { @@ -163,10 +177,24 @@ export class StageLasers extends SceneFeature { } this.lasers.forEach(l => { - l.mesh.visible = true; + l.mesh.visible = !['IDLE', 'COOLDOWN'].includes(this.activationState); + + let currentIntensity = intensity; + let flareScale = 1.0; + + if (this.activationState === 'WARMUP') { + currentIntensity = 0; + flareScale = 1.0 - this.stateTimer; + } else if (this.activationState === 'FADEOUT') { + const fade = Math.max(0, this.stateTimer / 1.0); + currentIntensity = 0; + flareScale = fade; + } + l.mesh.material.color.copy(color); - l.mesh.material.opacity = intensity; + l.mesh.material.opacity = currentIntensity; l.flare.material.color.copy(color); + l.flare.scale.setScalar(flareScale); // --- Movement Calculation --- let yaw = 0;