Feature: music visualization
This commit is contained in:
parent
383ba8baf1
commit
612a1bf501
@ -61,6 +61,15 @@ export class LightBall extends SceneFeature {
|
||||
mesh.position.y = 10 + Math.cos(time * driftSpeed * 1.3 + offset) * naveHeight/2 * 0.6;
|
||||
mesh.position.z = Math.cos(time * driftSpeed * 0.7 + offset) * length/2 * 0.8;
|
||||
light.position.copy(mesh.position);
|
||||
|
||||
// --- Music Visualization ---
|
||||
if (state.music) {
|
||||
const baseIntensity = 4.0;
|
||||
light.intensity = baseIntensity + state.music.beatIntensity * 3.0;
|
||||
|
||||
const baseScale = 1.0;
|
||||
mesh.scale.setScalar(baseScale + state.music.beatIntensity * 0.5);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
39
party-cathedral/src/scene/music-visualizer.js
Normal file
39
party-cathedral/src/scene/music-visualizer.js
Normal file
@ -0,0 +1,39 @@
|
||||
import { state } from '../state.js';
|
||||
import { SceneFeature } from './SceneFeature.js';
|
||||
import sceneFeatureManager from './SceneFeatureManager.js';
|
||||
|
||||
export class MusicVisualizer extends SceneFeature {
|
||||
constructor() {
|
||||
super();
|
||||
sceneFeatureManager.register(this);
|
||||
}
|
||||
|
||||
init() {
|
||||
// Initialize music state
|
||||
state.music = {
|
||||
bpm: 120,
|
||||
beatDuration: 60 / 120,
|
||||
measureDuration: (60 / 120) * 4,
|
||||
beatIntensity: 0,
|
||||
measurePulse: 0,
|
||||
};
|
||||
}
|
||||
|
||||
update(deltaTime) {
|
||||
if (!state.music) return;
|
||||
|
||||
const time = state.clock.getElapsedTime();
|
||||
|
||||
// --- Calculate Beat Intensity (pulses every beat) ---
|
||||
// This creates a sharp attack and slower decay (0 -> 1 -> 0)
|
||||
const beatProgress = (time % state.music.beatDuration) / state.music.beatDuration;
|
||||
state.music.beatIntensity = Math.pow(1.0 - beatProgress, 2);
|
||||
|
||||
// --- Calculate Measure Pulse (spikes every 4 beats) ---
|
||||
// This creates a very sharp spike for the torch flame effect
|
||||
const measureProgress = (time % state.music.measureDuration) / state.music.measureDuration;
|
||||
state.music.measurePulse = measureProgress < 0.2 ? Math.sin(measureProgress * Math.PI * 5) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
new MusicVisualizer();
|
||||
@ -97,7 +97,7 @@ export class PartyGuests extends SceneFeature {
|
||||
|
||||
const time = state.clock.getElapsedTime();
|
||||
const moveSpeed = 1.0; // Move slower
|
||||
const movementArea = { x: 10, z: 30, y: 0, centerZ: 0 };
|
||||
const movementArea = { x: 10, z: 30, y: 0, centerZ: 5 };
|
||||
const jumpChance = 0.05; // Jump way more
|
||||
const jumpDuration = 0.5;
|
||||
const jumpHeight = 0.1;
|
||||
@ -139,7 +139,12 @@ export class PartyGuests extends SceneFeature {
|
||||
mesh.position.y = movementArea.y + guestHeight / 2;
|
||||
}
|
||||
} else {
|
||||
if (Math.random() < jumpChance) {
|
||||
let currentJumpChance = jumpChance * deltaTime; // Base chance over time
|
||||
if (state.music && state.music.beatIntensity > 0.8) {
|
||||
currentJumpChance = 0.1; // High, fixed chance on the beat
|
||||
}
|
||||
|
||||
if (Math.random() < currentJumpChance) {
|
||||
guestObj.isJumping = true;
|
||||
guestObj.jumpHeight = jumpHeight + Math.random() * jumpVariance;
|
||||
guestObj.jumpStartTime = time;
|
||||
|
||||
0
party-cathedral/src/scene/pillar-candles.js
Normal file
0
party-cathedral/src/scene/pillar-candles.js
Normal file
@ -10,6 +10,7 @@ import { Stage } from './stage.js';
|
||||
import { MedievalMusicians } from './medieval-musicians.js';
|
||||
import { PartyGuests } from './party-guests.js';
|
||||
import { StageTorches } from './stage-torches.js';
|
||||
import { MusicVisualizer } from './music-visualizer.js';
|
||||
// Scene Features ^^^
|
||||
|
||||
// --- Scene Modeling Function ---
|
||||
|
||||
@ -86,11 +86,17 @@ export class StageTorches extends SceneFeature {
|
||||
|
||||
update(deltaTime) {
|
||||
this.torches.forEach(torch => {
|
||||
let measurePulse = 0;
|
||||
if (state.music) {
|
||||
measurePulse = state.music.measurePulse * 2.0; // Make flames jump higher
|
||||
}
|
||||
|
||||
// --- Animate Particles ---
|
||||
const positions = torch.particles.geometry.attributes.position.array;
|
||||
for (let i = 0; i < torch.particleData.length; i++) {
|
||||
const data = torch.particleData[i];
|
||||
data.life -= deltaTime;
|
||||
const yVelocity = data.velocity.y + measurePulse;
|
||||
|
||||
if (data.life <= 0) {
|
||||
// Reset particle
|
||||
@ -101,15 +107,21 @@ export class StageTorches extends SceneFeature {
|
||||
} else {
|
||||
// Update position
|
||||
positions[i * 3] += data.velocity.x * deltaTime;
|
||||
positions[i * 3 + 1] += data.velocity.y * deltaTime;
|
||||
positions[i * 3 + 1] += yVelocity * deltaTime;
|
||||
positions[i * 3 + 2] += data.velocity.z * deltaTime;
|
||||
}
|
||||
}
|
||||
torch.particles.geometry.attributes.position.needsUpdate = true;
|
||||
|
||||
// --- Flicker Light ---
|
||||
const flicker = Math.random() * 0.5;
|
||||
torch.light.intensity = 2.0 + flicker;
|
||||
const baseIntensity = 2.0;
|
||||
const flicker = Math.random() * 0.6;
|
||||
let beatPulse = 0;
|
||||
if (state.music) {
|
||||
beatPulse = state.music.beatIntensity * 1.5;
|
||||
}
|
||||
|
||||
torch.light.intensity = baseIntensity + flicker + beatPulse;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,10 +235,13 @@ export class StainedGlass extends SceneFeature {
|
||||
|
||||
update(deltaTime) {
|
||||
// Add a subtle pulsing glow to the windows
|
||||
const pulseSpeed = 0.5;
|
||||
const minIntensity = 0.1; // Increased intensity for a stronger glow
|
||||
const maxIntensity = 0.2;
|
||||
const intensity = minIntensity + (maxIntensity - minIntensity) * (0.5 * (1 + Math.sin(state.clock.getElapsedTime() * pulseSpeed)));
|
||||
let intensity = 0.15; // Base intensity
|
||||
|
||||
// --- Music Visualization ---
|
||||
if (state.music) {
|
||||
const beatPulse = state.music.beatIntensity * 0.3;
|
||||
intensity += beatPulse;
|
||||
}
|
||||
|
||||
// To make the glow match the vertex colors, we set the emissive color to white
|
||||
// and modulate its intensity. The final glow color will be vertexColor * emissive * emissiveIntensity.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user