import * as THREE from 'three'; interface Theme { floorLight: number; floorDark: number; wall: number; fog: number; } // 8 Stufen: Start + eine pro besiegten Boss (Golem, Krake, Minotaurus, // Spinnenkönigin, Frostriese, Erz-Nekromant, Drache) const THEMES: Theme[] = [ { floorLight: 0x668866, floorDark: 0x557755, wall: 0x776677, fog: 0x0d1117 }, // Start (Grün) { floorLight: 0x8a7a55, floorDark: 0x7a6a48, wall: 0x776055, fog: 0x141210 }, // Golem (Erdig) { floorLight: 0x3a4a66, floorDark: 0x2f3d55, wall: 0x44506a, fog: 0x0a1220 }, // Krake (Tinte) { floorLight: 0x8a4a3a, floorDark: 0x6e3a2c, wall: 0x7a4438, fog: 0x180d0b }, // Minotaurus (Asche) { floorLight: 0x4a7a4a, floorDark: 0x3a643a, wall: 0x4a6a4a, fog: 0x0a160d }, // Spinnenkönigin (Gift) { floorLight: 0x88bbcc, floorDark: 0x6a9ab0, wall: 0x7aa0b5, fog: 0x0d1a24 }, // Frostriese (Eis) { floorLight: 0x6a4a8a, floorDark: 0x543a70, wall: 0x5a3f74, fog: 0x140a20 }, // Erz-Nekromant (Lila) { floorLight: 0xaa6a33, floorDark: 0x8a5428, wall: 0x8f5c34, fog: 0x1e0f06 }, // Drache (Glut) ]; const LERP_SPEED = 2; export class Arena extends THREE.Group { private lightMats: THREE.MeshStandardMaterial[] = []; private darkMats: THREE.MeshStandardMaterial[] = []; private wallMats: THREE.MeshToonMaterial[] = []; private targets: | { floorLight: THREE.Color; floorDark: THREE.Color; wall: THREE.Color } | null = null; constructor() { super(); const tileSize = 10; const half = tileSize / 2; for (let x = -45; x < 50; x += tileSize) { for (let z = -45; z < 50; z += tileSize) { const isDark = ((x / tileSize + z / tileSize) & 1) === 0; const color = isDark ? 0x668866 : 0x557755; const tileGeom = new THREE.BoxGeometry(9.5, 0.3, 9.5); const tileMat = new THREE.MeshStandardMaterial({ color, roughness: 0.7, metalness: 0.0, }); const tile = new THREE.Mesh(tileGeom, tileMat); tile.position.set(x, -0.15, z); tile.receiveShadow = true; this.add(tile); (isDark ? this.darkMats : this.lightMats).push(tileMat); } } // Walls const wallGeom = new THREE.BoxGeometry(tileSize - 0.5, 2, 1); const wallMat = new THREE.MeshToonMaterial({ color: 0x776677 }); for (let coord = -50; coord <= 50; coord += tileSize) { this.createWall(coord, 49.5, wallGeom, wallMat); this.createWall(coord, -49.5, wallGeom, wallMat); } for (let coord = -50; coord <= 50; coord += tileSize) { this.createWall(49.5, coord, new THREE.BoxGeometry(1, 2, tileSize - 0.5), wallMat); this.createWall(-49.5, coord, new THREE.BoxGeometry(1, 2, tileSize - 0.5), wallMat); } for (const wall of this.children) { const mesh = wall as THREE.Mesh; if (mesh.material instanceof THREE.MeshToonMaterial) { this.wallMats.push(mesh.material); } } } private createWall(x: number, z: number, geom: THREE.BoxGeometry, mat: THREE.Material) { const wall = new THREE.Mesh(geom, mat); wall.position.set(x, 1, z); wall.castShadow = true; wall.receiveShadow = true; this.add(wall); } // Setzt die Ziel-Farben für eine Theme-Stufe und gibt die Nebel-Farbe zurück applyTheme(stage: number): THREE.Color { const t = THEMES[Math.min(Math.max(stage, 0), THEMES.length - 1)]; this.targets = { floorLight: new THREE.Color(t.floorLight), floorDark: new THREE.Color(t.floorDark), wall: new THREE.Color(t.wall), }; return new THREE.Color(t.fog); } // Lerpt die aktuellen Farben weich in Richtung Ziel-Theme update(dt: number) { if (!this.targets) return; const t = Math.min(1, dt * LERP_SPEED); for (const mat of this.lightMats) { mat.color.lerp(this.targets.floorLight, t); } for (const mat of this.darkMats) { mat.color.lerp(this.targets.floorDark, t); } for (const mat of this.wallMats) { mat.color.lerp(this.targets.wall, t); } } }