Refactor app.js to improve readability and organization
This commit is contained in:
@@ -8,7 +8,7 @@ import { UnrealBloomPass } from 'https://cdn.jsdelivr.net/npm/three@0.155.0/exam
|
|||||||
import { GammaCorrectionShader } from 'https://cdn.jsdelivr.net/npm/three@0.155.0/examples/jsm/shaders/GammaCorrectionShader.js';
|
import { GammaCorrectionShader } from 'https://cdn.jsdelivr.net/npm/three@0.155.0/examples/jsm/shaders/GammaCorrectionShader.js';
|
||||||
import { VignetteShader } from "https://cdn.jsdelivr.net/npm/three@0.155.0/examples/jsm/shaders/VignetteShader.js";
|
import { VignetteShader } from "https://cdn.jsdelivr.net/npm/three@0.155.0/examples/jsm/shaders/VignetteShader.js";
|
||||||
|
|
||||||
// ---- BASIS Three.js Szene ----
|
// ---- Basis Three.js Szene ----
|
||||||
const scene = new THREE.Scene();
|
const scene = new THREE.Scene();
|
||||||
const ASPECT = 3/2, SCALE = 15;
|
const ASPECT = 3/2, SCALE = 15;
|
||||||
const hw = SCALE/2, hh = (SCALE/ASPECT)/2;
|
const hw = SCALE/2, hh = (SCALE/ASPECT)/2;
|
||||||
@@ -23,7 +23,7 @@ renderer.shadowMap.enabled = true;
|
|||||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||||
container.appendChild(renderer.domElement);
|
container.appendChild(renderer.domElement);
|
||||||
|
|
||||||
// ---- POSTPROCESSING
|
// ---- Postprocessing ----
|
||||||
const foliageTexture = new THREE.TextureLoader().load('assets/sprites/foliage.png');
|
const foliageTexture = new THREE.TextureLoader().load('assets/sprites/foliage.png');
|
||||||
foliageTexture.colorSpace = THREE.SRGBColorSpace;
|
foliageTexture.colorSpace = THREE.SRGBColorSpace;
|
||||||
const FoliageOverlayShader = {
|
const FoliageOverlayShader = {
|
||||||
@@ -63,7 +63,7 @@ vignettePass.uniforms['darkness'].value = 1.35;
|
|||||||
composer.addPass(vignettePass);
|
composer.addPass(vignettePass);
|
||||||
composer.addPass(new ShaderPass(GammaCorrectionShader));
|
composer.addPass(new ShaderPass(GammaCorrectionShader));
|
||||||
|
|
||||||
// ---- Resize
|
// ---- Resize Handler ----
|
||||||
function onResize(){
|
function onResize(){
|
||||||
const W=container.clientWidth, H=container.clientHeight, winA=W/H;
|
const W=container.clientWidth, H=container.clientHeight, winA=W/H;
|
||||||
let vw,vh,vx,vy;
|
let vw,vh,vx,vy;
|
||||||
@@ -88,7 +88,7 @@ function onResize(){
|
|||||||
window.addEventListener('resize',onResize);
|
window.addEventListener('resize',onResize);
|
||||||
onResize();
|
onResize();
|
||||||
|
|
||||||
// ---- Environment Map
|
// ---- Environment Map ----
|
||||||
const texLoader = new THREE.TextureLoader();
|
const texLoader = new THREE.TextureLoader();
|
||||||
const pmremGen = new THREE.PMREMGenerator(renderer);
|
const pmremGen = new THREE.PMREMGenerator(renderer);
|
||||||
texLoader.load('assets/hdri/environment.jpg', tex => {
|
texLoader.load('assets/hdri/environment.jpg', tex => {
|
||||||
@@ -119,7 +119,7 @@ draco.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');
|
|||||||
const gltfLoader = new GLTFLoader();
|
const gltfLoader = new GLTFLoader();
|
||||||
gltfLoader.setDRACOLoader(draco);
|
gltfLoader.setDRACOLoader(draco);
|
||||||
|
|
||||||
// ---- Utility: GLBs laden (für Grundszene) ----
|
// ---- Utility: GLBs laden ----
|
||||||
async function loadGLB(path, pos, rotDeg, {receiveShadow=false, castShadow=false, emissive=null, visible=true, shadowOnly=false} = {}) {
|
async function loadGLB(path, pos, rotDeg, {receiveShadow=false, castShadow=false, emissive=null, visible=true, shadowOnly=false} = {}) {
|
||||||
const { scene: obj } = await gltfLoader.loadAsync(path);
|
const { scene: obj } = await gltfLoader.loadAsync(path);
|
||||||
obj.position.set(pos[0], pos[1], pos[2]);
|
obj.position.set(pos[0], pos[1], pos[2]);
|
||||||
@@ -209,8 +209,11 @@ const clock = new THREE.Clock();
|
|||||||
animate();
|
animate();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// ---- SPIRIT-KLASSE (aus alter Version, leicht adaptiert)
|
// ---- Spirit-Instanzen-Array (mehrere gleichzeitig!)
|
||||||
const MOVE_SPEED = 1; // wie im Original
|
const activeSpirits = [];
|
||||||
|
|
||||||
|
// ---- Spirit-Klasse ----
|
||||||
|
const MOVE_SPEED = 1;
|
||||||
class Spirit {
|
class Spirit {
|
||||||
constructor(obj3d, info) {
|
constructor(obj3d, info) {
|
||||||
this.clock = new THREE.Clock();
|
this.clock = new THREE.Clock();
|
||||||
@@ -220,9 +223,8 @@ class Spirit {
|
|||||||
this.info = info || {};
|
this.info = info || {};
|
||||||
this.grp.add(obj3d);
|
this.grp.add(obj3d);
|
||||||
|
|
||||||
// Positionierung + Drehung wie im Original
|
// Rotation & Position wie im Original
|
||||||
obj3d.rotation.x = -Math.PI;
|
obj3d.rotation.x = -Math.PI;
|
||||||
// Setze Position unterhalb Spinner (nutze aktuelle Spinner-Position)
|
|
||||||
let y = spinnerRed ? spinnerRed.position.y - 1.5 : 15;
|
let y = spinnerRed ? spinnerRed.position.y - 1.5 : 15;
|
||||||
this.grp.position.set(0, y, 0.88 - 0.6);
|
this.grp.position.set(0, y, 0.88 - 0.6);
|
||||||
|
|
||||||
@@ -265,8 +267,9 @@ class Spirit {
|
|||||||
}
|
}
|
||||||
// Bewegung nach unten
|
// Bewegung nach unten
|
||||||
this.grp.position.y -= MOVE_SPEED * dt;
|
this.grp.position.y -= MOVE_SPEED * dt;
|
||||||
if (t > 15) {
|
// LEBENSDAUER 20 Sekunden
|
||||||
scene.remove(this.grp);
|
if (t > 20) {
|
||||||
|
this.dispose();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -285,11 +288,9 @@ class Spirit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---- Render-Loop ----
|
// ---- Render-Loop ----
|
||||||
let currentSpirit = null;
|
|
||||||
window.currentSpirit = null;
|
|
||||||
|
|
||||||
function animate(){
|
function animate(){
|
||||||
const dt = clock.getDelta(), t = clock.getElapsedTime();
|
const dt = clock.getDelta(), t = clock.getElapsedTime();
|
||||||
|
|
||||||
// Spinner Animation
|
// Spinner Animation
|
||||||
const bob = Math.sin(t*1.2)*0.5;
|
const bob = Math.sin(t*1.2)*0.5;
|
||||||
const baseY = 16.55 + bob;
|
const baseY = 16.55 + bob;
|
||||||
@@ -318,42 +319,37 @@ function animate(){
|
|||||||
lightZ
|
lightZ
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Spirit animieren/entfernen
|
// Update & Entfernen aller aktiven Spirits
|
||||||
if (currentSpirit && currentSpirit.update) {
|
for (let i = activeSpirits.length - 1; i >= 0; i--) {
|
||||||
if (!currentSpirit.update(dt)) {
|
if (!activeSpirits[i].update(dt)) {
|
||||||
currentSpirit = null;
|
activeSpirits.splice(i, 1);
|
||||||
window.currentSpirit = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
composer.render(scene, camera);
|
composer.render(scene, camera);
|
||||||
requestAnimationFrame(animate);
|
requestAnimationFrame(animate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- WebSocket-basierter Spirit Spawn ----
|
// ---- WebSocket: Spirit erzeugen, Infobox updaten ----
|
||||||
const ws = new WebSocket(`ws://${location.host}`);
|
const ws = new WebSocket(`ws://${location.host}`);
|
||||||
|
|
||||||
ws.addEventListener('message', async (event) => {
|
ws.addEventListener('message', async (event) => {
|
||||||
const msg = JSON.parse(event.data);
|
const msg = JSON.parse(event.data);
|
||||||
if (msg.type === 'spirit') {
|
if (msg.type === 'spirit') {
|
||||||
await showSpirit(msg.data);
|
await spawnSpirit(msg.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function showSpirit(spirit) {
|
async function spawnSpirit(spirit) {
|
||||||
if (currentSpirit) {
|
|
||||||
currentSpirit.dispose();
|
|
||||||
currentSpirit = null;
|
|
||||||
window.currentSpirit = null;
|
|
||||||
}
|
|
||||||
console.log("Lade Spirit", spirit.modelUrl);
|
console.log("Lade Spirit", spirit.modelUrl);
|
||||||
|
|
||||||
// Modell laden
|
// Modell laden
|
||||||
const { scene: spiritObj } = await gltfLoader.loadAsync(spirit.modelUrl);
|
const { scene: spiritObj } = await gltfLoader.loadAsync(spirit.modelUrl);
|
||||||
|
|
||||||
// Spirit-Objekt mit Animation/Fading/Motion erzeugen!
|
// Spirit-Objekt mit Animation/Fading/Motion erzeugen!
|
||||||
currentSpirit = new Spirit(spiritObj, spirit);
|
const s = new Spirit(spiritObj, spirit);
|
||||||
window.currentSpirit = currentSpirit;
|
activeSpirits.push(s);
|
||||||
|
|
||||||
|
// Overlay zeigt immer den aktuellsten
|
||||||
updateSpiritOverlay(spirit);
|
updateSpiritOverlay(spirit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user