Refactor spinner logic and add spirit spawning methods
This commit is contained in:
@@ -121,6 +121,10 @@ const gltfLoader = new GLTFLoader();
|
|||||||
gltfLoader.setDRACOLoader(draco);
|
gltfLoader.setDRACOLoader(draco);
|
||||||
|
|
||||||
|
|
||||||
|
// Virtuelles Interdimensionales Geisterteleportationsgerät
|
||||||
|
// --- GLOBAL ---
|
||||||
|
const activeSpirits = [];
|
||||||
|
|
||||||
// Virtuelles Interdimensionales Geisterteleportationsgerät
|
// Virtuelles Interdimensionales Geisterteleportationsgerät
|
||||||
class SpinnerController {
|
class SpinnerController {
|
||||||
constructor(scene) {
|
constructor(scene) {
|
||||||
@@ -135,15 +139,15 @@ class SpinnerController {
|
|||||||
this.clock = new THREE.Clock();
|
this.clock = new THREE.Clock();
|
||||||
this.ws = null;
|
this.ws = null;
|
||||||
this.reconnectDelay = 2000;
|
this.reconnectDelay = 2000;
|
||||||
this.connected = false; // Verbindungsstatus
|
this.connected = false;
|
||||||
|
|
||||||
// Werte für sanften Übergang
|
// Sanfte Übergänge
|
||||||
this.transition = {
|
this.transition = {
|
||||||
emission: 3.0, targetEmission: 3.0,
|
emission: 3.0, targetEmission: 3.0,
|
||||||
bobMult: 0.5, targetBobMult: 0.5,
|
bobMult: 0.5, targetBobMult: 0.5,
|
||||||
rotSpeed: 1.2, targetRotSpeed: 1.2,
|
rotSpeed: 1.2, targetRotSpeed: 1.2,
|
||||||
lightIntensity: 5, targetLightIntensity: 5,
|
lightIntensity: 5, targetLightIntensity: 5,
|
||||||
lerpSpeed: 1/3 // 1/x Sekunden bis Ziel (hier: ca. 3s)
|
lerpSpeed: 1/3
|
||||||
};
|
};
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
@@ -154,15 +158,10 @@ class SpinnerController {
|
|||||||
this.spinnerBlue = await this.loadSpinner('assets/models/spinner_blue.glb', [0, 16.55, 0.88], [90, 0, 0], "#3380ff", 0.2);
|
this.spinnerBlue = await this.loadSpinner('assets/models/spinner_blue.glb', [0, 16.55, 0.88], [90, 0, 0], "#3380ff", 0.2);
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
const L = new THREE.PointLight(0xFFA230, 5, 30);
|
const L = new THREE.PointLight(0xFFA230, 5, 30); L.castShadow = true;
|
||||||
L.castShadow = true;
|
this.lights.push(L); this.scene.add(L);
|
||||||
this.lights.push(L);
|
const L2 = new THREE.PointLight(0xFFA230, 5, 30); L2.castShadow = true;
|
||||||
this.scene.add(L);
|
this.counterLights.push(L2); this.scene.add(L2);
|
||||||
|
|
||||||
const L2 = new THREE.PointLight(0xFFA230, 5, 30);
|
|
||||||
L2.castShadow = true;
|
|
||||||
this.counterLights.push(L2);
|
|
||||||
this.scene.add(L2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connectWebSocket();
|
this.connectWebSocket();
|
||||||
@@ -191,23 +190,16 @@ class SpinnerController {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Werte sanft angleichen ---
|
|
||||||
smoothTransition(dt) {
|
smoothTransition(dt) {
|
||||||
let T = this.transition;
|
let T = this.transition;
|
||||||
// Zielwerte setzen
|
|
||||||
if (this.connected) {
|
if (this.connected) {
|
||||||
T.targetEmission = 3.0;
|
T.targetEmission = 3.0; T.targetBobMult = 0.5;
|
||||||
T.targetBobMult = 0.5;
|
T.targetRotSpeed = 1.2; T.targetLightIntensity = 5;
|
||||||
T.targetRotSpeed = 1.2;
|
|
||||||
T.targetLightIntensity = 5;
|
|
||||||
} else {
|
} else {
|
||||||
T.targetEmission = 0.0;
|
T.targetEmission = 0.0; T.targetBobMult = 0.12;
|
||||||
T.targetBobMult = 0.12;
|
T.targetRotSpeed = 0.08; T.targetLightIntensity = 0;
|
||||||
T.targetRotSpeed = 0.08;
|
|
||||||
T.targetLightIntensity = 0;
|
|
||||||
}
|
}
|
||||||
// Lerp (sanft angleichen)
|
const s = T.lerpSpeed * dt;
|
||||||
const s = T.lerpSpeed * dt; // kleiner dt → smooth
|
|
||||||
T.emission += (T.targetEmission - T.emission) * s;
|
T.emission += (T.targetEmission - T.emission) * s;
|
||||||
T.bobMult += (T.targetBobMult - T.bobMult) * s;
|
T.bobMult += (T.targetBobMult - T.bobMult) * s;
|
||||||
T.rotSpeed += (T.targetRotSpeed - T.rotSpeed) * s;
|
T.rotSpeed += (T.targetRotSpeed - T.rotSpeed) * s;
|
||||||
@@ -216,19 +208,16 @@ class SpinnerController {
|
|||||||
|
|
||||||
animate(dt, t) {
|
animate(dt, t) {
|
||||||
this.smoothTransition(dt);
|
this.smoothTransition(dt);
|
||||||
|
|
||||||
const T = this.transition;
|
const T = this.transition;
|
||||||
const bob = Math.sin(t * 1.2) * T.bobMult;
|
const bob = Math.sin(t * 1.2) * T.bobMult;
|
||||||
const baseY = this.baseY + bob;
|
const baseY = this.baseY + bob;
|
||||||
|
|
||||||
// Spinner
|
|
||||||
if (this.spinnerRed && this.spinnerBlue) {
|
if (this.spinnerRed && this.spinnerBlue) {
|
||||||
this.spinnerRed.position.y = baseY + 0.8;
|
this.spinnerRed.position.y = baseY + 0.8;
|
||||||
this.spinnerBlue.position.y = baseY;
|
this.spinnerBlue.position.y = baseY;
|
||||||
this.spinnerRed.rotation.y -= T.rotSpeed * dt;
|
this.spinnerRed.rotation.y -= T.rotSpeed * dt;
|
||||||
this.spinnerBlue.rotation.y += T.rotSpeed * dt;
|
this.spinnerBlue.rotation.y += T.rotSpeed * dt;
|
||||||
|
|
||||||
// Emission auf beide Spinner anwenden
|
|
||||||
this.spinnerRed.traverse(c => {
|
this.spinnerRed.traverse(c => {
|
||||||
if (c.isMesh && c.material && c.material.isMeshStandardMaterial)
|
if (c.isMesh && c.material && c.material.isMeshStandardMaterial)
|
||||||
c.material.emissiveIntensity = T.emission;
|
c.material.emissiveIntensity = T.emission;
|
||||||
@@ -238,8 +227,6 @@ class SpinnerController {
|
|||||||
c.material.emissiveIntensity = T.emission;
|
c.material.emissiveIntensity = T.emission;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotierende Lichter (jetzt mit smooth intensity und Speed)
|
|
||||||
for (let i = 0; i < this.lights.length; i++) {
|
for (let i = 0; i < this.lights.length; i++) {
|
||||||
const ang = t * 0.8 + i * 2 * Math.PI / 3;
|
const ang = t * 0.8 + i * 2 * Math.PI / 3;
|
||||||
this.lights[i].position.set(
|
this.lights[i].position.set(
|
||||||
@@ -272,10 +259,10 @@ class SpinnerController {
|
|||||||
if (msg.type === 'spirit') {
|
if (msg.type === 'spirit') {
|
||||||
if (typeof msg.timeSinceSpawnMs === "number" && msg.timeSinceSpawnMs > 0) {
|
if (typeof msg.timeSinceSpawnMs === "number" && msg.timeSinceSpawnMs > 0) {
|
||||||
// Initiale Verbindung: Mit Offset
|
// Initiale Verbindung: Mit Offset
|
||||||
spawnSpiritWithOffset(msg.data, msg.timeSinceSpawnMs, msg.spiritIntervalMs);
|
this.spawnSpiritWithOffset(msg.data, msg.timeSinceSpawnMs, msg.spiritIntervalMs);
|
||||||
} else {
|
} else {
|
||||||
// Normales Timer-Event
|
// Normales Timer-Event
|
||||||
spawnSpirit(msg.data);
|
this.spawnSpirit(msg.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -290,6 +277,39 @@ class SpinnerController {
|
|||||||
this.ws.close();
|
this.ws.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Jetzt Methoden am Spinner! ---
|
||||||
|
async spawnSpirit(spiritData) {
|
||||||
|
let spawnPos = {
|
||||||
|
x: 0,
|
||||||
|
y: this.spinnerRed ? this.spinnerRed.position.y - 1.5 : 15,
|
||||||
|
z: 0.88
|
||||||
|
};
|
||||||
|
const modelUrl = spiritData['Model URL'] || spiritData.modelUrl;
|
||||||
|
const { scene: gltfScene } = await gltfLoader.loadAsync(modelUrl);
|
||||||
|
const spirit = new Spirit(this.scene, gltfScene, spiritData, spawnPos);
|
||||||
|
spirit.clock.start();
|
||||||
|
activeSpirits.push(spirit);
|
||||||
|
}
|
||||||
|
|
||||||
|
async spawnSpiritWithOffset(spiritData, timeSinceSpawnMs = 0, spiritIntervalMs = 20000) {
|
||||||
|
let startY = this.spinnerRed ? this.spinnerRed.position.y - 1.5 : 15;
|
||||||
|
let offset = (typeof timeSinceSpawnMs === 'number' && timeSinceSpawnMs > 0) ? timeSinceSpawnMs / 1000 : 0;
|
||||||
|
let lifeTime = (spiritIntervalMs ? spiritIntervalMs : 20000) / 1000;
|
||||||
|
const despawnSpeed = 0.8;
|
||||||
|
let spawnPos = { x: 0, y: startY - (despawnSpeed * offset), z: 0.88 };
|
||||||
|
|
||||||
|
const modelUrl = spiritData['Model URL'] || spiritData.modelUrl;
|
||||||
|
const { scene: gltfScene } = await gltfLoader.loadAsync(modelUrl);
|
||||||
|
|
||||||
|
const spirit = new Spirit(this.scene, gltfScene, spiritData, spawnPos);
|
||||||
|
spirit.clock.start();
|
||||||
|
if (offset > 0 && offset < lifeTime) {
|
||||||
|
spirit.clock.elapsedTime = offset;
|
||||||
|
}
|
||||||
|
spirit.lifeTime = lifeTime;
|
||||||
|
activeSpirits.push(spirit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -429,32 +449,6 @@ async function loadGLB(path, pos, rotDeg, { receiveShadow = false, castShadow =
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Spirit spawnen ----
|
|
||||||
async function spawnSpirit(spiritData) {
|
|
||||||
let spawnPos = { x: 0, y: spinnerController && spinnerController.spinnerRed ? spinnerController.spinnerRed.position.y - 1.5 : 15, z: 0.88 };
|
|
||||||
const modelUrl = spiritData['Model URL'] || spiritData.modelUrl; // Fallback!
|
|
||||||
const { scene: gltfScene } = await gltfLoader.loadAsync(modelUrl);
|
|
||||||
const spirit = new Spirit(scene, gltfScene, spiritData, spawnPos);
|
|
||||||
spirit.clock.start(); // neu!
|
|
||||||
activeSpirits.push(spirit);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function spawnSpiritWithOffset(spiritData, timeSinceSpawnMs = 0, spiritIntervalMs = 20000) {
|
|
||||||
let spawnPos = { x: 0, y: spinnerController && spinnerController.spinnerRed ? spinnerController.spinnerRed.position.y - 1.5 : 15, z: 0.88 };
|
|
||||||
const modelUrl = spiritData['Model URL'] || spiritData.modelUrl;
|
|
||||||
const { scene: gltfScene } = await gltfLoader.loadAsync(modelUrl);
|
|
||||||
|
|
||||||
let offset = (typeof timeSinceSpawnMs === 'number' && timeSinceSpawnMs > 0) ? timeSinceSpawnMs / 1000 : 0;
|
|
||||||
let lifeTime = (spiritIntervalMs ? spiritIntervalMs : 20000) / 1000;
|
|
||||||
|
|
||||||
const spirit = new Spirit(scene, gltfScene, spiritData, spawnPos);
|
|
||||||
spirit.clock.start();
|
|
||||||
if (offset > 0 && offset < lifeTime) {
|
|
||||||
spirit.clock.elapsedTime = offset;
|
|
||||||
}
|
|
||||||
spirit.lifeTime = lifeTime;
|
|
||||||
activeSpirits.push(spirit);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Overlay-Logik ----
|
// ---- Overlay-Logik ----
|
||||||
let lastOverlaySpiritData = null;
|
let lastOverlaySpiritData = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user