From 2811fdbbd8e4670b4cf7ece5e55a0c54af5cc0c5 Mon Sep 17 00:00:00 2001 From: Dejvino Date: Fri, 21 Nov 2025 22:16:30 +0100 Subject: [PATCH] Feature: more colored light balls --- party-cathedral/src/scene/light-ball.js | 84 ++++++++++++++----------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/party-cathedral/src/scene/light-ball.js b/party-cathedral/src/scene/light-ball.js index a5df2ca..7e338fa 100644 --- a/party-cathedral/src/scene/light-ball.js +++ b/party-cathedral/src/scene/light-ball.js @@ -3,58 +3,70 @@ import { state } from '../state.js'; import { SceneFeature } from './SceneFeature.js'; import sceneFeatureManager from './SceneFeatureManager.js'; +// --- Dimensions from room-walls.js for positioning --- +const naveWidth = 12; +const naveHeight = 15; +const length = 40; + export class LightBall extends SceneFeature { constructor() { super(); - this.ball = null; - this.light = null; + this.lightBalls = []; sceneFeatureManager.register(this); } init() { - // --- Dimensions from room-walls.js for positioning --- - const naveWidth = 12; - const naveHeight = 15; - const length = 40; - // --- Ball Properties --- - const ballRadius = 1.0; - const ballColor = 0xffffff; // White light - const lightIntensity = 6.0; + const ballRadius = 0.4; + const lightIntensity = 5.0; + const lightColors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0x558800]; // Red, Green, Blue, Yellow - // --- Create the Ball --- - const ballGeometry = new THREE.SphereGeometry(ballRadius, 32, 32); - const ballMaterial = new THREE.MeshBasicMaterial({ color: ballColor, emissive: ballColor, emissiveIntensity: 1.0 }); - this.ball = new THREE.Mesh(ballGeometry, ballMaterial); - this.ball.castShadow = false; - this.ball.receiveShadow = false; + lightColors.forEach(color => { + // --- Create the Ball --- + const ballGeometry = new THREE.SphereGeometry(ballRadius, 32, 32); + const ballMaterial = new THREE.MeshBasicMaterial({ color: color, emissive: color, emissiveIntensity: 1.0 }); + const ball = new THREE.Mesh(ballGeometry, ballMaterial); + ball.castShadow = false; + ball.receiveShadow = false; - // --- Create the Light --- - this.light = new THREE.PointLight(ballColor, lightIntensity, length / 2); // Adjust range to cathedral size - this.light.castShadow = true; - this.light.shadow.mapSize.width = 512; - this.light.shadow.mapSize.height = 512; - this.light.shadow.camera.near = 0.1; - this.light.shadow.camera.far = length / 2; + // --- Create the Light --- + const light = new THREE.PointLight(color, lightIntensity, length / 1.5); + light.castShadow = true; + light.shadow.mapSize.width = 512; + light.shadow.mapSize.height = 512; + light.shadow.camera.near = 0.1; + light.shadow.camera.far = length / 2; - // --- Initial Position --- - this.ball.position.set(0, naveHeight * 0.7, 0); // Near the ceiling - this.light.position.copy(this.ball.position); + // --- Initial Position --- + ball.position.set( + (Math.random() - 0.5) * naveWidth, + naveHeight * 0.6 + Math.random() * 4, + (Math.random() - 0.5) * length * 0.8 + ); + light.position.copy(ball.position); - state.scene.add(this.ball); - state.scene.add(this.light); + state.scene.add(ball); + state.scene.add(light); + + this.lightBalls.push({ + mesh: ball, + light: light, + driftSpeed: 0.2 + Math.random() * 0.2, + driftAmplitude: 4.0 + Math.random() * 4.0, + offset: Math.random() * Math.PI * 6, + }); + }); } update(deltaTime) { - // --- Animate the Ball --- const time = state.clock.getElapsedTime(); - const driftSpeed = 0.5; - const driftAmplitude = 10.0; - - this.ball.position.x = Math.sin(time * driftSpeed) * driftAmplitude; - this.ball.position.y = 10 + Math.cos(time * driftSpeed * 1.3) * driftAmplitude * 0.5; // bobbing - this.ball.position.z = Math.cos(time * driftSpeed * 0.7) * driftAmplitude; - this.light.position.copy(this.ball.position); + this.lightBalls.forEach(lb => { + const { mesh, light, driftSpeed, offset } = lb; + mesh.position.x = Math.sin(time * driftSpeed + offset) * naveWidth/2 * 0.8; + 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); + }); } }