/* * CREATIVE SPACE STATION DOCKING PRELOADER * Realistic and immersive space experience */ console.log('🚀 Space Station Docking Preloader loaded!'); // Creative Space Station Docking Preloader class SpaceStationPreloader { constructor() { this.loadingProgress = 0; this.isDestroyed = false; this.init(); } init() { this.createContainer(); this.startLoadingSequence(); } createContainer() { // Remove immediate preloader first const immediatePreloader = document.getElementById('immediatePreloader'); if (immediatePreloader) { immediatePreloader.remove(); } // Remove any existing JS preloader const existing = document.getElementById('spacePreloader'); if (existing) existing.remove(); // Create main container this.container = document.createElement('div'); this.container.id = 'spacePreloader'; this.container.innerHTML = `
COSMOPEDIA
Deep Space Command Center
DOCKING SEQUENCE
0%
Approaching Space Station...
`; // Add creative space station styles const style = document.createElement('style'); style.textContent = ` #spacePreloader { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: #000; z-index: 999999; overflow: hidden; font-family: 'Orbitron', 'Space Grotesk', monospace; } .space-scene { position: relative; width: 100%; height: 100%; perspective: 1000px; } .stars-field { position: absolute; width: 200%; height: 200%; top: -50%; left: -50%; background-image: radial-gradient(1px 1px at 20px 30px, #fff, transparent), radial-gradient(1px 1px at 40px 70px, #fff, transparent), radial-gradient(1px 1px at 90px 40px, #fff, transparent), radial-gradient(1px 1px at 130px 80px, #fff, transparent), radial-gradient(1px 1px at 160px 30px, #fff, transparent); background-repeat: repeat; background-size: 200px 100px; animation: starsMove 60s linear infinite; opacity: 0.8; } .nebula-cloud { position: absolute; top: 20%; right: 10%; width: 300px; height: 200px; background: radial-gradient(ellipse, rgba(138, 43, 226, 0.3) 0%, rgba(75, 0, 130, 0.2) 30%, rgba(0, 191, 255, 0.1) 60%, transparent 80%); border-radius: 50%; filter: blur(2px); animation: nebulaFloat 20s ease-in-out infinite; } .space-station { position: absolute; top: 50%; left: 75%; transform: translate(-50%, -50%); width: 200px; height: 200px; } .station-core { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 60px; height: 60px; background: linear-gradient(45deg, #333, #666); border-radius: 8px; box-shadow: 0 0 20px rgba(0, 150, 255, 0.5), inset 0 0 10px rgba(0, 100, 200, 0.3); } .station-ring { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border: 3px solid rgba(0, 150, 255, 0.7); border-radius: 50%; box-shadow: 0 0 15px rgba(0, 150, 255, 0.5); } .ring-1 { width: 120px; height: 120px; animation: stationRotate 15s linear infinite; } .ring-2 { width: 160px; height: 160px; animation: stationRotate 25s linear infinite reverse; } .station-antenna { position: absolute; top: 25%; left: 50%; transform: translateX(-50%); width: 2px; height: 40px; background: linear-gradient(to top, #444, #0096ff); box-shadow: 0 0 10px rgba(0, 150, 255, 0.8); } .docking-bay { position: absolute; bottom: 20%; left: 50%; transform: translateX(-50%); width: 30px; height: 15px; background: rgba(0, 255, 0, 0.3); border: 2px solid rgba(0, 255, 0, 0.8); box-shadow: 0 0 15px rgba(0, 255, 0, 0.6); animation: dockingPulse 2s ease-in-out infinite; } .approaching-ship { position: absolute; top: 65%; left: 20%; transform: translate(-50%, -50%); width: 80px; height: 40px; animation: shipApproach 8s ease-in-out infinite; } .ship-body { position: absolute; top: 50%; left: 0; transform: translateY(-50%); width: 50px; height: 20px; background: linear-gradient(45deg, #555, #888); clip-path: polygon(0% 50%, 20% 0%, 80% 0%, 100% 50%, 80% 100%, 20% 100%); box-shadow: 0 0 10px rgba(255, 255, 255, 0.3); } .ship-engines { position: absolute; top: 50%; right: 0; transform: translateY(-50%); } .engine { position: absolute; width: 8px; height: 8px; background: radial-gradient(circle, #00ffff, #0080ff); border-radius: 50%; box-shadow: 0 0 15px rgba(0, 255, 255, 0.8); animation: enginePulse 0.5s ease-in-out infinite alternate; } .engine-1 { top: -8px; } .engine-2 { top: 4px; } .engine-trail { position: absolute; top: 50%; right: -20px; transform: translateY(-50%); width: 30px; height: 4px; background: linear-gradient(to right, rgba(0, 255, 255, 0.8), transparent); border-radius: 50px; animation: trailFlicker 0.3s ease-in-out infinite; } .ui-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .hud-frame { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .hud-corner { position: absolute; width: 40px; height: 40px; border: 2px solid rgba(0, 255, 255, 0.8); box-shadow: 0 0 10px rgba(0, 255, 255, 0.5); } .tl { top: 20px; left: 20px; border-right: none; border-bottom: none; } .tr { top: 20px; right: 20px; border-left: none; border-bottom: none; } .bl { bottom: 20px; left: 20px; border-right: none; border-top: none; } .br { bottom: 20px; right: 20px; border-left: none; border-top: none; } .mission-info { position: absolute; top: 50px; left: 50%; transform: translateX(-50%); text-align: center; color: #fff; } .mission-title { font-size: 2.5rem; font-weight: 700; color: #00ffff; text-shadow: 0 0 20px rgba(0, 255, 255, 0.8); margin-bottom: 0.5rem; letter-spacing: 0.2rem; animation: titleGlow 3s ease-in-out infinite alternate; } .mission-subtitle { font-size: 1rem; color: #aaa; margin-bottom: 2rem; letter-spacing: 0.1rem; } .docking-status { margin-bottom: 1rem; } .status-label { font-size: 0.9rem; color: #00ff00; margin-bottom: 1rem; text-shadow: 0 0 10px rgba(0, 255, 0, 0.5); } .progress-container { position: relative; width: 300px; height: 6px; background: rgba(255, 255, 255, 0.1); border-radius: 3px; margin: 0 auto 1rem auto; overflow: hidden; } .progress-bar { height: 100%; background: linear-gradient(90deg, #00ffff, #00ff00); border-radius: 3px; width: 0%; transition: width 0.3s ease; box-shadow: 0 0 15px rgba(0, 255, 255, 0.6); } .progress-glow { position: absolute; top: 0; left: 0; height: 100%; width: 20px; background: rgba(255, 255, 255, 0.5); border-radius: 3px; animation: progressSweep 2s ease-in-out infinite; } .progress-percent { font-size: 1.2rem; color: #00ffff; font-weight: bold; margin-bottom: 1rem; } .system-status { font-size: 0.9rem; color: #ffffff; opacity: 0.8; } .radar-display { position: absolute; bottom: 50px; right: 50px; width: 120px; height: 120px; } .radar-circle { position: relative; width: 100%; height: 100%; border: 2px solid rgba(0, 255, 0, 0.5); border-radius: 50%; background: radial-gradient(circle, rgba(0, 255, 0, 0.1), transparent 70%); } .radar-sweep { position: absolute; top: 50%; left: 50%; width: 2px; height: 50%; background: linear-gradient(to top, rgba(0, 255, 0, 0.8), transparent); transform-origin: bottom center; animation: radarSweep 3s linear infinite; } .radar-blip { position: absolute; width: 6px; height: 6px; border-radius: 50%; animation: blipPulse 2s ease-in-out infinite; } .station-blip { top: 30%; right: 20%; background: rgba(0, 150, 255, 0.8); box-shadow: 0 0 10px rgba(0, 150, 255, 0.6); } .ship-blip { bottom: 25%; left: 25%; background: rgba(255, 255, 0, 0.8); box-shadow: 0 0 10px rgba(255, 255, 0, 0.6); } /* Animations */ @keyframes starsMove { 0% { transform: translate(0, 0); } 100% { transform: translate(-100px, -50px); } } @keyframes nebulaFloat { 0%, 100% { transform: translate(0, 0) scale(1); } 50% { transform: translate(20px, -10px) scale(1.1); } } @keyframes stationRotate { 0% { transform: translate(-50%, -50%) rotate(0deg); } 100% { transform: translate(-50%, -50%) rotate(360deg); } } @keyframes dockingPulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } } @keyframes shipApproach { 0% { transform: translate(-50%, -50%) scale(0.8); } 50% { transform: translate(-40%, -45%) scale(1); } 100% { transform: translate(-50%, -50%) scale(0.8); } } @keyframes enginePulse { 0% { transform: scale(1); opacity: 1; } 100% { transform: scale(1.3); opacity: 0.7; } } @keyframes trailFlicker { 0%, 100% { opacity: 0.8; } 50% { opacity: 0.4; } } @keyframes titleGlow { 0% { text-shadow: 0 0 20px rgba(0, 255, 255, 0.8); } 100% { text-shadow: 0 0 30px rgba(0, 255, 255, 1), 0 0 40px rgba(0, 255, 255, 0.5); } } @keyframes progressSweep { 0% { left: -20px; } 100% { left: 100%; } } @keyframes radarSweep { 0% { transform: translate(-50%, 0) rotate(0deg); } 100% { transform: translate(-50%, 0) rotate(360deg); } } @keyframes blipPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.5; transform: scale(1.2); } } .space-exit { animation: spaceExit 1s ease-out forwards; } @keyframes spaceExit { 0% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(1.1); } } @media (max-width: 768px) { .mission-title { font-size: 2rem; } .progress-container { width: 250px; } .radar-display { bottom: 30px; right: 30px; width: 100px; height: 100px; } } `; document.head.appendChild(style); document.body.appendChild(this.container); document.body.style.overflow = 'hidden'; } startLoadingSequence() { const progressBar = document.getElementById('dockingProgress'); const percentText = document.getElementById('dockingPercent'); const statusText = document.getElementById('systemStatus'); const messages = [ "Approaching Space Station...", "Requesting Docking Permission...", "Permission Granted - Bay 7", "Aligning Docking Trajectory...", "Reducing Approach Velocity...", "Engaging Magnetic Clamps...", "Docking Sequence Complete!", "Welcome to Cosmopedia" ]; const updateProgress = () => { if (this.isDestroyed) return; this.loadingProgress += Math.random() * 6 + 3; if (this.loadingProgress >= 100) { this.loadingProgress = 100; progressBar.style.width = '100%'; percentText.textContent = '100%'; statusText.textContent = messages[messages.length - 1]; setTimeout(() => { if (!this.isDestroyed) { this.destroy(); } }, 1200); return; } // Update progress progressBar.style.width = this.loadingProgress + '%'; percentText.textContent = Math.floor(this.loadingProgress) + '%'; // Update message based on progress const messageIndex = Math.floor((this.loadingProgress / 100) * (messages.length - 1)); statusText.textContent = messages[messageIndex] || messages[0]; setTimeout(updateProgress, 120 + Math.random() * 80); }; updateProgress(); } destroy() { this.isDestroyed = true; // Add exit animation this.container.classList.add('space-exit'); setTimeout(() => { // Remove DOM elements if (this.container && this.container.parentNode) { this.container.parentNode.removeChild(this.container); } // Restore page document.body.style.overflow = ''; console.log('🚀 Space Station Docking Complete!'); }, 1000); } } // Initialize function with error handling function initSpacePreloader() { try { console.log('🚀 Initiating Space Station Docking Sequence...'); // For testing, always show (uncomment for session storage) // if (sessionStorage.getItem('spacePreloaderShown')) { // console.log('⏭️ Preloader already shown this session'); // return; // } new SpaceStationPreloader(); // sessionStorage.setItem('spacePreloaderShown', 'true'); } catch (error) { console.error('Preloader error:', error); document.body.style.overflow = ''; } } // Start immediately with safety checks function safeStart() { try { initSpacePreloader(); } catch (error) { console.error('Failed to start preloader:', error); // Ensure page is usable even if preloader fails document.body.style.overflow = ''; } } // Multiple start points for reliability if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', safeStart); } else { safeStart(); } // Emergency cleanup functions window.clearSpacePreloader = () => { const preloader = document.getElementById('spacePreloader'); if (preloader) preloader.remove(); document.body.style.overflow = ''; sessionStorage.clear(); }; window.clearPreloader = () => { window.clearSpacePreloader(); }; window.resetSpacePreloader = () => { sessionStorage.removeItem('spacePreloaderShown'); location.reload(); }; class CinemaSpacePreloader { constructor() { this.scene = null; this.camera = null; this.renderer = null; this.spaceship = null; this.planets = []; this.particles = []; this.nebula = null; this.blackhole = null; this.comet = null; this.engineTrails = []; this.loadingProgress = 0; this.animationId = null; this.isDestroyed = false; this.loadingMessages = [ "Initializing Quantum Drive...", "Scanning Deep Space...", "Aligning Stellar Coordinates...", "Charging Warp Core...", "Calculating Trajectory...", "Engaging Hyperdrive...", "Reality Matrix Stabilized!", "Jump Complete!" ]; this.init(); } init() { this.createContainer(); this.initThreeJS(); this.createEnvironment(); this.createSpaceship(); this.createPlanets(); this.createComet(); this.createBlackhole(); this.createParticleField(); this.startLoadingSequence(); this.animate(); } createContainer() { // Remove any existing preloader const existing = document.getElementById('ultimateSpacePreloader'); if (existing) existing.remove(); // Create main container this.container = document.createElement('div'); this.container.id = 'ultimateSpacePreloader'; this.container.innerHTML = `
COSMOPEDIA
Initializing Quantum Drive...
0%
${Array.from({length: 30}, () => '
').join('')}
`; // Add ultimate styles const style = document.createElement('style'); style.textContent = ` #ultimateSpacePreloader { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: #000000; z-index: 999999; overflow: hidden; font-family: 'Orbitron', 'Space Grotesk', monospace; } .preloader-canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .preloader-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(ellipse at center, rgba(0,20,40,0.3) 0%, rgba(0,0,0,0.8) 70%); display: flex; align-items: center; justify-content: center; } .loading-interface { text-align: center; position: relative; z-index: 10; } .hologram-title { font-size: 4rem; font-weight: 700; color: #00ffff; text-shadow: 0 0 10px #00ffff, 0 0 20px #00ffff, 0 0 40px #00ffff, 0 0 80px #00ffff; margin-bottom: 3rem; letter-spacing: 0.5rem; animation: hologramFlicker 3s ease-in-out infinite; position: relative; background: linear-gradient(45deg, #00ffff, #ff0080, #00ff80, #ffff00); background-size: 400% 400%; background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; animation: hologramFlicker 3s ease-in-out infinite, gradientShift 8s ease-in-out infinite; } .hologram-title::before { content: attr(data-text); position: absolute; top: 0; left: 0; color: #ff0080; z-index: -1; animation: hologramGlitch 5s infinite; } .scan-lines { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: repeating-linear-gradient( 0deg, transparent, transparent 2px, rgba(0,255,255,0.03) 2px, rgba(0,255,255,0.03) 4px ); animation: scanMove 2s linear infinite; pointer-events: none; } .status-display { margin-bottom: 2rem; } .status-message { font-size: 1.5rem; color: #00ccff; margin-bottom: 3rem; text-shadow: 0 0 10px rgba(0,204,255,0.5); animation: statusPulse 2s ease-in-out infinite; } .progress-hologram { position: relative; width: 200px; height: 200px; margin: 0 auto 2rem auto; } .progress-core { position: absolute; top: 50%; left: 50%; width: 80px; height: 80px; transform: translate(-50%, -50%); border: 3px solid #00ffff; border-radius: 50%; background: radial-gradient(circle, rgba(0,255,255,0.2) 0%, transparent 70%); box-shadow: 0 0 20px #00ffff, inset 0 0 20px rgba(0,255,255,0.1); animation: coreEnergy 2s ease-in-out infinite; } .progress-rings { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .ring { position: absolute; border: 2px solid transparent; border-radius: 50%; animation: ringRotate 3s linear infinite; } .ring1 { top: 10px; left: 10px; right: 10px; bottom: 10px; border-top-color: #ff0080; border-right-color: #ff0080; animation-duration: 2s; box-shadow: 0 0 15px rgba(255,0,128,0.5); } .ring2 { top: 25px; left: 25px; right: 25px; bottom: 25px; border-bottom-color: #00ff80; border-left-color: #00ff80; animation-duration: 3s; animation-direction: reverse; box-shadow: 0 0 15px rgba(0,255,128,0.5); } .ring3 { top: 40px; left: 40px; right: 40px; bottom: 40px; border-top-color: #ffff00; border-bottom-color: #ffff00; animation-duration: 4s; box-shadow: 0 0 15px rgba(255,255,0,0.5); } .progress-percent { font-size: 2rem; font-weight: bold; color: #00ffff; text-shadow: 0 0 20px #00ffff; animation: percentGlow 1s ease-in-out infinite alternate; } .quantum-particles { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .quantum-dot { position: absolute; width: 4px; height: 4px; background: #00ffff; border-radius: 50%; box-shadow: 0 0 10px #00ffff; animation: quantumFloat 6s linear infinite; } .quantum-dot:nth-child(even) { background: #ff0080; box-shadow: 0 0 10px #ff0080; animation-duration: 8s; } .quantum-dot:nth-child(3n) { background: #00ff80; box-shadow: 0 0 10px #00ff80; animation-duration: 7s; } @keyframes hologramFlicker { 0%, 100% { opacity: 1; } 5% { opacity: 0.8; } 10% { opacity: 1; } 15% { opacity: 0.9; } 20% { opacity: 1; } } @keyframes hologramGlitch { 0%, 90%, 100% { transform: translate(0); } 10% { transform: translate(-2px, 1px); } 20% { transform: translate(1px, -1px); } 30% { transform: translate(-1px, 1px); } } @keyframes scanMove { 0% { transform: translateY(-100vh); } 100% { transform: translateY(100vh); } } @keyframes statusPulse { 0%, 100% { opacity: 0.8; } 50% { opacity: 1; } } @keyframes coreEnergy { 0%, 100% { transform: translate(-50%, -50%) scale(1); } 50% { transform: translate(-50%, -50%) scale(1.1); } } @keyframes ringRotate { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes percentGlow { 0% { text-shadow: 0 0 20px #00ffff; } 100% { text-shadow: 0 0 30px #00ffff, 0 0 40px #00ffff; } } @keyframes quantumFloat { 0% { transform: translate(0, 100vh) scale(0); opacity: 0; } 10% { opacity: 1; transform: scale(1); } 90% { opacity: 1; } 100% { transform: translate(${Math.random() * 200 - 100}px, -100vh) scale(0); opacity: 0; } } @keyframes ultimateExit { 0% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(1.2); } } @keyframes gradientShift { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } } @keyframes ultimateExit { 0% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(1.2); } } .preloader-exit { animation: ultimateExit 1s ease-out forwards; } @media (max-width: 768px) { .hologram-title { font-size: 2.5rem; } .progress-hologram { width: 150px; height: 150px; } } particles = this.container.querySelectorAll('.quantum-dot'); particles.forEach((particle, index) => { particle.style.left = Math.random() * 100 + '%'; particle.style.animationDelay = (index * 0.2) + 's'; }); document.body.appendChild(this.container); document.body.style.overflow = 'hidden'; } initThreeJS() { const canvas = document.createElement('canvas'); this.container.querySelector('.preloader-canvas').appendChild(canvas); // Scene this.scene = new THREE.Scene(); this.scene.fog = new THREE.FogExp2(0x000011, 0.0003); // Camera this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); this.camera.position.set(0, 20, 100); // Renderer with enhanced settings this.renderer = new THREE.WebGLRenderer({ canvas: canvas, alpha: true, antialias: true, powerPreference: "high-performance" }); this.renderer.setSize(window.innerWidth, window.innerHeight); this.renderer.setClearColor(0x000000, 0); this.renderer.shadowMap.enabled = true; this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; // Enhanced lighting system const ambientLight = new THREE.AmbientLight(0x404040, 0.4); this.scene.add(ambientLight); // Main light const mainLight = new THREE.DirectionalLight(0x00aaff, 1.5); mainLight.position.set(50, 50, 50); mainLight.castShadow = true; mainLight.shadow.mapSize.width = 2048; mainLight.shadow.mapSize.height = 2048; this.scene.add(mainLight); // Accent lights const light1 = new THREE.PointLight(0xff0080, 2, 100); light1.position.set(-50, 20, 30); this.scene.add(light1); const light2 = new THREE.PointLight(0x00ff80, 1.5, 80); light2.position.set(50, -20, -30); this.scene.add(light2); const light3 = new THREE.PointLight(0xffff00, 1, 60); light3.position.set(0, 50, -50); this.scene.add(light3); } createEnvironment() { // Create massive starfield const starGeometry = new THREE.BufferGeometry(); const starCount = 5000; const positions = []; const colors = []; for (let i = 0; i < starCount; i++) { positions.push( (Math.random() - 0.5) * 800, (Math.random() - 0.5) * 800, (Math.random() - 0.5) * 800 ); // Different colored stars const colorChoice = Math.random(); if (colorChoice < 0.7) { colors.push(1, 1, 1); // White } else if (colorChoice < 0.85) { colors.push(0.8, 0.8, 1); // Blue } else { colors.push(1, 0.8, 0.6); // Orange } } starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); starGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3)); const starMaterial = new THREE.PointsMaterial({ size: 2, vertexColors: true, transparent: true, opacity: 0.8, blending: THREE.AdditiveBlending }); this.stars = new THREE.Points(starGeometry, starMaterial); this.scene.add(this.stars); // Create nebula clouds for (let i = 0; i < 8; i++) { const nebulaGeometry = new THREE.SphereGeometry(25, 16, 16); const nebulaMaterial = new THREE.MeshBasicMaterial({ color: new THREE.Color().setHSL(Math.random(), 0.8, 0.3), transparent: true, opacity: 0.1, side: THREE.DoubleSide, blending: THREE.AdditiveBlending }); const nebula = new THREE.Mesh(nebulaGeometry, nebulaMaterial); nebula.position.set( (Math.random() - 0.5) * 400, (Math.random() - 0.5) * 200, (Math.random() - 0.5) * 400 ); nebula.scale.set( 1 + Math.random() * 2, 0.5 + Math.random(), 1 + Math.random() * 2 ); this.scene.add(nebula); } } createSpaceship() { const spaceshipGroup = new THREE.Group(); // Main fuselage - sleek design const fuselageGeometry = new THREE.CylinderGeometry(0.8, 2.5, 12, 16); const fuselageMaterial = new THREE.MeshPhongMaterial({ color: 0x4A90E2, shininess: 150, specular: 0x111111 }); const fuselage = new THREE.Mesh(fuselageGeometry, fuselageMaterial); fuselage.rotation.z = Math.PI / 2; fuselage.castShadow = true; spaceshipGroup.add(fuselage); // Wings - more realistic const wingGeometry = new THREE.BoxGeometry(8, 0.5, 3); const wingMaterial = new THREE.MeshPhongMaterial({ color: 0x7B68EE, shininess: 100 }); const leftWing = new THREE.Mesh(wingGeometry, wingMaterial); leftWing.position.set(-3, 3, 0); leftWing.rotation.z = -0.2; leftWing.castShadow = true; spaceshipGroup.add(leftWing); const rightWing = new THREE.Mesh(wingGeometry, wingMaterial); rightWing.position.set(-3, -3, 0); rightWing.rotation.z = 0.2; rightWing.castShadow = true; spaceshipGroup.add(rightWing); // Engine clusters with glow for (let i = 0; i < 4; i++) { const engineGeometry = new THREE.CylinderGeometry(0.3, 0.5, 2, 8); const engineMaterial = new THREE.MeshBasicMaterial({ color: 0x00ffff, transparent: true, opacity: 0.9 }); const engine = new THREE.Mesh(engineGeometry, engineMaterial); const angle = (i / 4) * Math.PI * 2; engine.position.set( 5, Math.cos(angle) * 1.5, Math.sin(angle) * 1.5 ); engine.rotation.z = Math.PI / 2; spaceshipGroup.add(engine); // Engine glow effect const glowGeometry = new THREE.SphereGeometry(0.8, 8, 8); const glowMaterial = new THREE.MeshBasicMaterial({ color: 0x00ffff, transparent: true, opacity: 0.3, blending: THREE.AdditiveBlending }); const glow = new THREE.Mesh(glowGeometry, glowMaterial); glow.position.copy(engine.position); glow.position.x += 1; spaceshipGroup.add(glow); } spaceshipGroup.position.set(-80, 10, 20); spaceshipGroup.scale.set(1.5, 1.5, 1.5); this.spaceship = spaceshipGroup; this.scene.add(this.spaceship); } createPlanets() { // Create several planets with different characteristics const planetData = [ { radius: 8, color: 0x4169E1, distance: 120, speed: 0.005, name: 'earth' }, { radius: 6, color: 0xff6b47, distance: 180, speed: 0.003, name: 'mars' }, { radius: 12, color: 0xFFD700, distance: 250, speed: 0.002, name: 'saturn' }, { radius: 10, color: 0xFF4500, distance: 320, speed: 0.001, name: 'jupiter' } ]; planetData.forEach((data, index) => { const planetGroup = new THREE.Group(); // Main planet const planetGeometry = new THREE.SphereGeometry(data.radius, 32, 32); const planetMaterial = new THREE.MeshPhongMaterial({ color: data.color, shininess: 30, transparent: true, opacity: 0.9 }); const planet = new THREE.Mesh(planetGeometry, planetMaterial); planet.castShadow = true; planet.receiveShadow = true; planetGroup.add(planet); // Add atmosphere const atmosphereGeometry = new THREE.SphereGeometry(data.radius * 1.15, 32, 32); const atmosphereMaterial = new THREE.MeshBasicMaterial({ color: data.color, transparent: true, opacity: 0.15, side: THREE.BackSide, blending: THREE.AdditiveBlending }); const atmosphere = new THREE.Mesh(atmosphereGeometry, atmosphereMaterial); planetGroup.add(atmosphere); // Special features for specific planets if (data.name === 'saturn') { // Add Saturn's rings for (let i = 0; i < 4; i++) { const ringGeometry = new THREE.RingGeometry(data.radius * (1.5 + i * 0.3), data.radius * (1.7 + i * 0.3), 64); const ringMaterial = new THREE.MeshBasicMaterial({ color: new THREE.Color().setHSL(0.1 + i * 0.05, 0.8, 0.6), transparent: true, opacity: 0.7 - i * 0.1, side: THREE.DoubleSide }); const ring = new THREE.Mesh(ringGeometry, ringMaterial); ring.rotation.x = Math.PI / 2 + (Math.random() - 0.5) * 0.1; planetGroup.add(ring); } } if (data.name === 'earth') { // Add Earth's moon const moonGeometry = new THREE.SphereGeometry(data.radius * 0.25, 16, 16); const moonMaterial = new THREE.MeshPhongMaterial({ color: 0xaaaaaa, shininess: 5 }); const moon = new THREE.Mesh(moonGeometry, moonMaterial); moon.position.set(data.radius * 2, 0, 0); planetGroup.add(moon); } planetGroup.position.set(data.distance, Math.random() * 40 - 20, Math.random() * 40 - 20); this.planets.push({ mesh: planetGroup, speed: data.speed, distance: data.distance }); this.scene.add(planetGroup); }); } createComet() { const cometGroup = new THREE.Group(); // Comet nucleus const nucleusGeometry = new THREE.SphereGeometry(2, 16, 16); const nucleusMaterial = new THREE.MeshPhongMaterial({ color: 0xaaaaaa, shininess: 10 }); const nucleus = new THREE.Mesh(nucleusGeometry, nucleusMaterial); nucleus.castShadow = true; cometGroup.add(nucleus); // Comet coma (fuzzy atmosphere) const comaGeometry = new THREE.SphereGeometry(8, 16, 16); const comaMaterial = new THREE.MeshBasicMaterial({ color: 0x00aaff, transparent: true, opacity: 0.2, blending: THREE.AdditiveBlending }); const coma = new THREE.Mesh(comaGeometry, comaMaterial); cometGroup.add(coma); // Comet tail - create multiple segments for (let i = 0; i < 20; i++) { const tailGeometry = new THREE.SphereGeometry(1 + i * 0.5, 8, 8); const tailMaterial = new THREE.MeshBasicMaterial({ color: new THREE.Color().setHSL(0.6, 0.8, 0.8), transparent: true, opacity: 0.3 - i * 0.01, blending: THREE.AdditiveBlending }); const tailSegment = new THREE.Mesh(tailGeometry, tailMaterial); tailSegment.position.set(-i * 3, Math.sin(i * 0.5) * 2, Math.cos(i * 0.3) * 1); cometGroup.position.set(-200, 50, -100); this.comet = cometGroup; this.scene.add(this.comet); } this.scene.add(this.comet); } this.scene.add(planetGroup); }); } createBlackhole() { const blackholeGroup = new THREE.Group(); // Event horizon const horizonGeometry = new THREE.SphereGeometry(15, 32, 32); const horizonMaterial = new THREE.MeshBasicMaterial({ color: 0x000000, transparent: true, opacity: 0.9 }); const horizon = new THREE.Mesh(horizonGeometry, horizonMaterial); blackholeGroup.add(horizon); // Accretion disk for (let i = 0; i < 5; i++) { const ringGeometry = new THREE.TorusGeometry(20 + i * 8, 2, 8, 64); const ringMaterial = new THREE.MeshBasicMaterial({ color: new THREE.Color().setHSL(0.1 + i * 0.1, 1, 0.5), transparent: true, opacity: 0.6 - i * 0.1, blending: THREE.AdditiveBlending }); const ring = new THREE.Mesh(ringGeometry, ringMaterial); ring.rotation.x = Math.PI / 2 + Math.random() * 0.2; blackholeGroup.add(ring); } blackholeGroup.position.set(200, -100, -200); this.blackhole = blackholeGroup; this.scene.add(this.blackhole); } createParticleField() { // Create multiple particle systems for (let system = 0; system < 4; system++) { const particleCount = 1500; const geometry = new THREE.BufferGeometry(); const positions = []; const colors = []; const velocities = []; for (let i = 0; i < particleCount; i++) { positions.push( (Math.random() - 0.5) * 600, (Math.random() - 0.5) * 300, (Math.random() - 0.5) * 600 ); // Different particle colors per system if (system === 0) { colors.push(0, 1, 1); // Cyan } else if (system === 1) { colors.push(1, 0, 0.5); // Magenta } else if (system === 2) { colors.push(0, 1, 0.5); // Green } else { colors.push(1, 1, 0); // Yellow } velocities.push( (Math.random() - 0.5) * 0.3, (Math.random() - 0.5) * 0.2, (Math.random() - 0.5) * 0.3 ); } geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3)); geometry.setAttribute('velocity', new THREE.Float32BufferAttribute(velocities, 3)); const material = new THREE.PointsMaterial({ size: 1.5 + system * 0.5, vertexColors: true, transparent: true, opacity: 0.7, blending: THREE.AdditiveBlending }); const particles = new THREE.Points(geometry, material); this.particles.push(particles); this.scene.add(particles); } } startLoadingSequence() { let messageIndex = 0; const messageElement = document.getElementById('statusMessage'); const progressCore = document.getElementById('progressCore'); const progressPercent = document.getElementById('progressPercent'); const updateProgress = () => { if (this.isDestroyed) return; this.loadingProgress += Math.random() * 4 + 2; if (this.loadingProgress >= 100) { this.loadingProgress = 100; if (this.loadingProgress >= 100) { this.loadingProgress = 100; messageElement.textContent = this.loadingMessages[this.loadingMessages.length - 1]; progressPercent.textContent = '100%'; setTimeout(() => { if (!this.isDestroyed) { this.destroy(); } }, 1500); return; } // Update progress core intensity const intensity = this.loadingProgress / 100; progressCore.style.boxShadow = `0 0 ${20 + intensity * 30}px #00ffff, inset 0 0 ${20 + intensity * 20}px rgba(0,255,255,${0.1 + intensity * 0.3})`; progressPercent.textContent = Math.floor(this.loadingProgress) + '%'; // Update message const expectedIndex = Math.floor((this.loadingProgress / 100) * (this.loadingMessages.length - 1)); if (expectedIndex !== messageIndex && expectedIndex < this.loadingMessages.length - 1) { messageIndex = expectedIndex; messageElement.textContent = this.loadingMessages[messageIndex]; } // Update message const expectedIndex = Math.floor((this.loadingProgress / 100) * (this.loadingMessages.length - 1)); if (expectedIndex !== messageIndex && expectedIndex < this.loadingMessages.length - 1) { messageIndex = expectedIndex; messageElement.textContent = this.loadingMessages[messageIndex]; } time = Date.now() * 0.001; // Rotate stars if (this.stars) { this.stars.rotation.y += 0.002; } // Animate spaceship if (this.spaceship) { this.spaceship.position.y = Math.sin(time * 2) * 0.5; this.spaceship.rotation.z = Math.sin(time) * 0.1; } // Animate planets in orbital motion this.planets.forEach((planetObj) => { planetObj.mesh.rotation.y += planetObj.speed * 2; // Planet rotation // Orbital motion around center const orbitSpeed = planetObj.speed * 0.5; const angle = time * orbitSpeed; animate() { if (this.isDestroyed) return; this.animationId = requestAnimationFrame(() => this.animate()); const time = Date.now() * 0.001; // Animate twinkling stars if (this.stars) { this.stars.rotation.y += 0.001; this.stars.rotation.x += 0.0005; // Animate star opacity for twinkling effect const starMaterial = this.stars.material; starMaterial.opacity = 0.8 + Math.sin(time * 2) * 0.2; } // Animate spaceship with enhanced effects if (this.spaceship) { this.spaceship.position.y = 10 + Math.sin(time * 2) * 2; this.spaceship.position.x = -80 + Math.sin(time * 0.5) * 10; this.spaceship.rotation.z = Math.sin(time) * 0.1; this.spaceship.rotation.y = Math.sin(time * 0.3) * 0.05; // Animate engine glows this.spaceship.children.forEach((child) => { if (child.material && child.material.color && child.material.color.r === 0) { // This is an engine glow child.material.opacity = 0.3 + Math.sin(time * 10) * 0.2; child.scale.setScalar(0.8 + Math.sin(time * 8) * 0.3); } }); } // Animate planets in orbital motion this.planets.forEach((planetObj) => { planetObj.mesh.rotation.y += planetObj.speed * 2; // Planet rotation // Orbital motion around center const orbitSpeed = planetObj.speed * 0.5; const angle = time * orbitSpeed; planetObj.mesh.position.x = Math.cos(angle) * planetObj.distance; planetObj.mesh.position.z = Math.sin(angle) * planetObj.distance; // Slight vertical oscillation planetObj.mesh.position.y += Math.sin(time * planetObj.speed * 20) * 0.2; }); // Animate comet if (this.comet) { // Comet follows an elliptical path const cometSpeed = time * 0.3; this.comet.position.x = -200 + Math.cos(cometSpeed) * 150; this.comet.position.y = 50 + Math.sin(cometSpeed * 0.7) * 30; this.comet.position.z = -100 + Math.sin(cometSpeed) * 80; // Rotate comet slowly this.comet.rotation.y += 0.01; // Animate tail segments this.comet.children.forEach((child, index) => { if (index > 1) { // Skip nucleus and coma child.position.y += Math.sin(time * 3 + index) * 0.1; child.scale.setScalar(0.8 + Math.sin(time * 2 + index) * 0.2); } }); } // Animate blackhole if (this.blackhole) { this.blackhole.rotation.y += 0.005; this.blackhole.children.forEach((ring, index) => { if (index > 0) { // Skip the event horizon ring.rotation.z += 0.01 * (index + 1); } }); } // Animate particles this.particles.forEach((particleSystem) => { const positions = particleSystem.geometry.attributes.position.array; const velocities = particleSystem.geometry.attributes.velocity.array; for (let i = 0; i < positions.length; i += 3) { positions[i] += velocities[i]; positions[i + 1] += velocities[i + 1]; positions[i + 2] += velocities[i + 2]; // Reset particles that go too far if (Math.abs(positions[i]) > 300 || Math.abs(positions[i + 1]) > 150 || Math.abs(positions[i + 2]) > 300) { positions[i] = (Math.random() - 0.5) * 600; positions[i + 1] = (Math.random() - 0.5) * 300; positions[i + 2] = (Math.random() - 0.5) * 600; } } particleSystem.geometry.attributes.position.needsUpdate = true; }); // Cinematic camera movement with parallax const parallaxX = Math.sin(time * 0.5) * 8; const parallaxY = 20 + Math.cos(time * 0.3) * 5; const parallaxZ = 100 + Math.sin(time * 0.2) * 20; this.camera.position.x = parallaxX; this.camera.position.y = parallaxY; this.camera.position.z = parallaxZ; // Look at a point slightly offset for dynamic feel this.camera.lookAt( Math.sin(time * 0.1) * 5, Math.cos(time * 0.15) * 3, 0 ); this.renderer.render(this.scene, this.camera); } // Remove DOM elements if (this.container && this.container.parentNode) { this.container.parentNode.removeChild(this.container); } // Restore page document.body.style.overflow = ''; console.log('✨ Cinema-Quality Space Preloader completed!'); }, 1200); } } // Start immediately - ALWAYS SHOW FOR TESTING (remove comment to enable session storage) function initCinemaPreloader() { console.log('🎬 Checking session storage...'); // TEMPORARILY DISABLED FOR TESTING - UNCOMMENT TO ENABLE SESSION STORAGE // if (sessionStorage.getItem('spacePreloaderShown')) { // console.log('⏭️ Preloader already shown this session'); // return; // } console.log('🎬 Creating Cinema-Quality Space Preloader!'); if (window.THREE) { // Remove immediate preloader first const immediatePreloader = document.getElementById('immediatePreloader'); if (immediatePreloader) { immediatePreloader.remove(); } new CinemaSpacePreloader(); // sessionStorage.setItem('spacePreloaderShown', 'true'); } else { console.log('Loading Three.js...'); const script = document.createElement('script'); script.src = 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js'; script.onload = () => { console.log('Three.js loaded! Creating Cinema-Quality Space Preloader!'); // Remove immediate preloader first const immediatePreloader = document.getElementById('immediatePreloader'); if (immediatePreloader) { immediatePreloader.remove(); } new CinemaSpacePreloader(); // sessionStorage.setItem('spacePreloaderShown', 'true'); }; script.onerror = () => { console.error('Failed to load Three.js'); // Remove immediate preloader on error const immediatePreloader = document.getElementById('immediatePreloader'); if (immediatePreloader) { immediatePreloader.remove(); document.body.style.overflow = ''; } }; document.head.appendChild(script); } } // Start immediately if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCinemaPreloader); } else { initCinemaPreloader(); } // Global function to reset preloader (for testing) window.resetProfessionalPreloader = () => { sessionStorage.removeItem('spacePreloaderShown'); location.reload(); }; // Clear preloader session on development window.addEventListener('beforeunload', () => { if (window.location.hostname === 'localhost' || window.location.search.includes('dev')) { // Only clear on localhost for development // sessionStorage.removeItem('spacePreloaderShown'); } }); // Emergency function to clear and restart window.clearSpacePreloader = () => { sessionStorage.clear(); location.reload(); };