music-video-gen/tv-player/src/scene/door.js
2025-11-16 15:59:23 +01:00

120 lines
4.0 KiB
JavaScript

import * as THREE from 'three';
import { state } from '../state.js';
let doorGroupPanel;
let outsideMaterial; // Declare outsideMaterial globally
let glowIntensity = 0.0;
let glowDirection = 1; // 1 for increasing, -1 for decreasing
const DOOR_STATES = {
RESTING: 'resting',
OPENING: 'opening',
CLOSING: 'closing',
};
let doorState = DOOR_STATES.RESTING;
let stateTimer = 0;
export function createDoor(x, z, rotY) {
const doorWidth = 1;
const doorGroup = new THREE.Group();
doorGroup.position.set(x, 1.1, z); // Centered vertically for a 2.2m door
doorGroup.rotation.set(0, rotY, 0);
// Door Frame
const frameMaterial = new THREE.MeshPhongMaterial({ color: 0x473e3a }); // Dark wood for frame
const frameTop = new THREE.Mesh(new THREE.BoxGeometry(1.2, 0.1, 0.15), frameMaterial);
frameTop.position.set(0, 1.15, 0);
frameTop.castShadow = true;
doorGroup.add(frameTop);
const frameLeft = new THREE.Mesh(new THREE.BoxGeometry(0.1, 2.3, 0.15), frameMaterial);
frameLeft.position.set(-0.55, 0.05, 0);
frameLeft.castShadow = true;
doorGroup.add(frameLeft);
const frameRight = new THREE.Mesh(new THREE.BoxGeometry(0.1, 2.3, 0.15), frameMaterial);
frameRight.position.set(0.55, 0.05, 0);
frameRight.castShadow = true;
doorGroup.add(frameRight);
// Outside darkness
outsideMaterial = new THREE.MeshPhongMaterial({ color: 0x150505, emissive: 0x000000, shininess: 50 });
const outside = new THREE.Mesh(new THREE.BoxGeometry(doorWidth, 2.2, 0.04), outsideMaterial);
outside.position.set(0, 0, 0);
doorGroup.add(outside);
// Door group
doorGroupPanel = new THREE.Group();
// Main Door Panel
const doorMaterial = new THREE.MeshPhongMaterial({ color: 0x8b5a2b, shininess: 10 }); // Lighter wood for door
const door = new THREE.Mesh(new THREE.BoxGeometry(doorWidth, 2.2, 0.08), doorMaterial);
door.position.set(doorWidth/2, 0, 0);
door.castShadow = true;
door.receiveShadow = true;
doorGroupPanel.add(door);
// Door Knob
const knobMaterial = new THREE.MeshPhongMaterial({ color: 0xd4af37, shininess: 100 }); // Gold/Brass
const knob = new THREE.Mesh(new THREE.SphereGeometry(0.05, 16, 16), knobMaterial);
knob.position.set(doorWidth/2 + 0.4, 0, 0.06); // Position on the right side of the door
knob.castShadow = true;
doorGroupPanel.add(knob);
doorGroupPanel.position.x = -doorWidth/2;
doorGroupPanel.rotation.y = 0;
doorGroup.add(doorGroupPanel);
state.scene.add(doorGroup);
}
export function updateDoor() {
const speed = 0.0002;
const minAngle = 0;
const maxAngle = -0.7;
stateTimer -= 1 / 60; // Assuming 60fps
if (stateTimer <= 0) {
const nextState = Math.random();
if (nextState < 0.4) {
doorState = DOOR_STATES.RESTING;
stateTimer = 2 + Math.random() * 5;
} else if (nextState < 0.7) {
doorState = DOOR_STATES.OPENING;
stateTimer = 2 + Math.random() * 4;
} else {
doorState = DOOR_STATES.CLOSING;
stateTimer = 3 + Math.random() * 3;
}
}
switch (doorState) {
case DOOR_STATES.OPENING:
if (doorGroupPanel.rotation.y > maxAngle) {
doorGroupPanel.rotation.y -= speed;
}
break;
case DOOR_STATES.CLOSING:
if (doorGroupPanel.rotation.y < minAngle) {
doorGroupPanel.rotation.y += speed;
}
break;
}
// Outside material pulsating glow
if (outsideMaterial) {
const glowMin = 0.001;
const glowMax = 0.01;
const glowSpeed = 0.0001; // Speed of the pulsation
glowIntensity += glowDirection * glowSpeed;
if (glowIntensity >= glowMax) {
glowIntensity = glowMax;
glowDirection = -1;
} else if (glowIntensity <= glowMin) {
glowIntensity = glowMin;
glowDirection = 1;
}
outsideMaterial.emissive.setRGB(glowIntensity, 0, 0);
}
}