diff --git a/app.js b/app.js index 5a028f6..3d66a79 100644 --- a/app.js +++ b/app.js @@ -9,6 +9,8 @@ const NEXUS = { constellationLine: 0x334488, constellationFade: 0x112244, accent: 0x4488ff, + avatarCore: 0x66aaff, + avatarGlow: 0x2255cc, } }; @@ -112,6 +114,31 @@ function buildConstellationLines() { const constellationLines = buildConstellationLines(); scene.add(constellationLines); +// === TIMMY AVATAR === +// A floating icosahedron representing Timmy's presence near the terminal hub. +const avatarGeo = new THREE.IcosahedronGeometry(0.55, 1); +const avatarMat = new THREE.MeshBasicMaterial({ + color: NEXUS.colors.avatarCore, + wireframe: true, + transparent: true, + opacity: 0.85, +}); +const timmyAvatar = new THREE.Mesh(avatarGeo, avatarMat); +timmyAvatar.position.set(1.6, 0.4, 0); +scene.add(timmyAvatar); + +// Outer shell — slightly larger wireframe for holographic depth +const avatarShellGeo = new THREE.IcosahedronGeometry(0.8, 1); +const avatarShellMat = new THREE.MeshBasicMaterial({ + color: NEXUS.colors.avatarGlow, + wireframe: true, + transparent: true, + opacity: 0.25, +}); +const timmyShell = new THREE.Mesh(avatarShellGeo, avatarShellMat); +timmyShell.position.copy(timmyAvatar.position); +scene.add(timmyShell); + // === MOUSE-DRIVEN ROTATION === let mouseX = 0; let mouseY = 0; @@ -182,6 +209,17 @@ function animate() { // Subtle pulse on constellation opacity constellationLines.material.opacity = 0.12 + Math.sin(elapsed * 0.5) * 0.06; + // Timmy avatar — float, rotate, and pulse + const floatY = Math.sin(elapsed * 0.8) * 0.12; + timmyAvatar.position.y = 0.4 + floatY; + timmyShell.position.y = timmyAvatar.position.y; + timmyAvatar.rotation.y = elapsed * 0.6; + timmyAvatar.rotation.x = elapsed * 0.3; + timmyShell.rotation.y = -elapsed * 0.4; + timmyShell.rotation.x = elapsed * 0.2; + timmyAvatar.material.opacity = 0.7 + Math.sin(elapsed * 1.2) * 0.15; + timmyShell.material.opacity = 0.15 + Math.sin(elapsed * 0.9 + 1) * 0.1; + renderer.render(scene, camera); }