// Robot Interactions - Make robots come alive with personality! class RobotInteractions { constructor() { this.robots = []; this.mousePosition = { x: 0, y: 0 }; this.isInitialized = false; // Robot moods and states this.moods = ['happy', 'curious', 'excited', 'sleepy', 'thinking']; this.currentMood = 'happy'; // Easter egg: secret robot dance this.konami = []; this.konamiCode = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'b', 'a']; } init() { if (this.isInitialized) return; this.findRobots(); this.setupEventListeners(); this.startIdleAnimations(); this.setupEasterEggs(); this.isInitialized = true; } findRobots() { // Find all robot elements const robotElements = document.querySelectorAll('.robot-head, .robot-container, .model-robot, .platform-robot, .tool-robot'); robotElements.forEach(robot => { const eyes = robot.querySelectorAll('.robot-eye'); if (eyes.length > 0) { this.robots.push({ element: robot, eyes: Array.from(eyes), originalPositions: Array.from(eyes).map(eye => { const rect = eye.getBoundingClientRect(); return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }; }), isBlinking: false, mood: 'happy' }); } }); } setupEventListeners() { // Track mouse movement document.addEventListener('mousemove', (e) => { this.mousePosition = { x: e.clientX, y: e.clientY }; this.updateEyes(); }); // Robot hover interactions this.robots.forEach(robot => { robot.element.addEventListener('mouseenter', () => this.onRobotHover(robot)); robot.element.addEventListener('mouseleave', () => this.onRobotLeave(robot)); robot.element.addEventListener('click', () => this.onRobotClick(robot)); }); // Keyboard interactions document.addEventListener('keydown', (e) => this.handleKeyPress(e)); } updateEyes() { this.robots.forEach(robot => { if (robot.isBlinking) return; robot.eyes.forEach((eye, index) => { // Skip sleeping or closed eyes if (eye.classList.contains('sleeping') || eye.classList.contains('closed')) return; const eyeRect = eye.getBoundingClientRect(); const eyeCenter = { x: eyeRect.left + eyeRect.width / 2, y: eyeRect.top + eyeRect.height / 2 }; // Calculate angle between eye and mouse const angle = Math.atan2( this.mousePosition.y - eyeCenter.y, this.mousePosition.x - eyeCenter.x ); // Calculate distance (capped for natural movement) const distance = Math.min( Math.hypot( this.mousePosition.x - eyeCenter.x, this.mousePosition.y - eyeCenter.y ) / 10, 3 // Maximum pupil movement ); // Move the pupil (eye shine) const pupil = eye.querySelector('::after') || eye; const offsetX = Math.cos(angle) * distance; const offsetY = Math.sin(angle) * distance; // Apply transform to eye or create inner pupil if (!eye.querySelector('.pupil')) { const pupilElement = document.createElement('div'); pupilElement.className = 'pupil'; eye.appendChild(pupilElement); } const pupilElement = eye.querySelector('.pupil'); if (pupilElement) { pupilElement.style.transform = `translate(${offsetX}px, ${offsetY}px)`; } }); }); } onRobotHover(robot) { // Add excited animation robot.element.classList.add('hover-active'); // Make eyes bigger robot.eyes.forEach(eye => { eye.style.transform = 'scale(1.2)'; eye.classList.add('excited'); }); // Add blush effect this.addBlush(robot); // Random reaction const reactions = ['happy', 'surprised', 'love']; const reaction = reactions[Math.floor(Math.random() * reactions.length)]; if (reaction === 'love') { robot.eyes.forEach(eye => eye.classList.add('love')); } } onRobotLeave(robot) { robot.element.classList.remove('hover-active'); // Reset eyes robot.eyes.forEach(eye => { eye.style.transform = ''; eye.classList.remove('excited', 'love'); }); // Remove blush this.removeBlush(robot); } onRobotClick(robot) { // Trigger a fun animation this.makeRobotJump(robot); this.makeRobotSpeak(robot); // Easter egg: clicking 5 times makes robot do a dance if (!robot.clickCount) robot.clickCount = 0; robot.clickCount++; if (robot.clickCount >= 5) { this.robotDance(robot); robot.clickCount = 0; } } makeRobotJump(robot) { robot.element.style.animation = 'robotJump 0.6s ease-out'; setTimeout(() => { robot.element.style.animation = ''; }, 600); } makeRobotSpeak(robot) { const messages = [ "Hello there! 👋", "Beep boop! 🤖", "AI at your service!", "Let's build something cool!", "Privacy first! 🔒", "Running locally! đŸ’Ē", "*happy robot noises*", "01001000 01101001! (Hi in binary!)" ]; const message = messages[Math.floor(Math.random() * messages.length)]; this.showSpeechBubble(robot, message); } showSpeechBubble(robot, message) { // Remove existing bubble const existingBubble = robot.element.querySelector('.robot-speech-bubble'); if (existingBubble) existingBubble.remove(); // Create new bubble const bubble = document.createElement('div'); bubble.className = 'robot-speech-bubble'; bubble.innerHTML = ` ${message}
`; robot.element.appendChild(bubble); // Remove after 3 seconds setTimeout(() => { bubble.classList.add('fade-out'); setTimeout(() => bubble.remove(), 300); }, 3000); } startIdleAnimations() { // Random blinking setInterval(() => { this.robots.forEach(robot => { if (Math.random() < 0.1 && !robot.isBlinking) { this.makeRobotBlink(robot); } }); }, 2000); // Random mood changes setInterval(() => { const robot = this.robots[Math.floor(Math.random() * this.robots.length)]; if (robot && Math.random() < 0.3) { this.changeRobotMood(robot); } }, 5000); } makeRobotBlink(robot) { robot.isBlinking = true; robot.eyes.forEach(eye => { eye.style.transition = 'height 0.1s ease'; eye.style.height = '2px'; setTimeout(() => { eye.style.height = ''; robot.isBlinking = false; }, 150); }); } changeRobotMood(robot) { const moods = ['thinking', 'happy', 'curious']; const mood = moods[Math.floor(Math.random() * moods.length)]; switch(mood) { case 'thinking': this.showThinkingBubbles(robot); break; case 'happy': this.makeRobotSmile(robot); break; case 'curious': this.makeRobotLookAround(robot); break; } } showThinkingBubbles(robot) { const bubbles = document.createElement('div'); bubbles.className = 'thinking-bubbles'; bubbles.innerHTML = `
💭
`; robot.element.appendChild(bubbles); setTimeout(() => { bubbles.classList.add('fade-out'); setTimeout(() => bubbles.remove(), 300); }, 3000); } makeRobotSmile(robot) { const smile = robot.element.querySelector('.robot-smile'); if (smile) { smile.classList.add('big-smile'); setTimeout(() => smile.classList.remove('big-smile'), 2000); } } makeRobotLookAround(robot) { let direction = -1; const lookInterval = setInterval(() => { robot.eyes.forEach(eye => { eye.style.transform = `translateX(${direction * 3}px)`; }); direction *= -1; }, 500); setTimeout(() => { clearInterval(lookInterval); robot.eyes.forEach(eye => { eye.style.transform = ''; }); }, 2000); } addBlush(robot) { const head = robot.element.querySelector('.robot-head') || robot.element; ['left', 'right'].forEach(side => { const blush = document.createElement('div'); blush.className = `robot-blush ${side}`; head.appendChild(blush); }); } removeBlush(robot) { const blushes = robot.element.querySelectorAll('.robot-blush'); blushes.forEach(blush => blush.remove()); } setupEasterEggs() { // Konami code for robot dance party document.addEventListener('keydown', (e) => { this.konami.push(e.key); this.konami = this.konami.slice(-10); if (this.konami.join(',') === this.konamiCode.join(',')) { this.robotDanceParty(); } }); // Secret robot activation phrase let secretPhrase = ''; document.addEventListener('keypress', (e) => { secretPhrase += e.key; secretPhrase = secretPhrase.slice(-10); if (secretPhrase.includes('robot')) { this.activateSecretRobotMode(); } }); } robotDanceParty() { document.body.classList.add('robot-dance-party'); // Make all robots dance this.robots.forEach((robot, index) => { setTimeout(() => { this.robotDance(robot); }, index * 200); }); // Add disco lights this.addDiscoLights(); // Stop after 10 seconds setTimeout(() => { document.body.classList.remove('robot-dance-party'); this.removeDiscoLights(); }, 10000); } robotDance(robot) { robot.element.classList.add('dancing'); // Random dance moves const dances = ['wiggle', 'spin', 'bounce', 'shake']; const dance = dances[Math.floor(Math.random() * dances.length)]; robot.element.style.animation = `robot-${dance} 1s ease-in-out infinite`; setTimeout(() => { robot.element.style.animation = ''; robot.element.classList.remove('dancing'); }, 5000); } addDiscoLights() { const disco = document.createElement('div'); disco.className = 'disco-lights'; disco.innerHTML = `
đŸĒŠ
`; document.body.appendChild(disco); } removeDiscoLights() { const disco = document.querySelector('.disco-lights'); if (disco) disco.remove(); } activateSecretRobotMode() { // Make all robots super happy this.robots.forEach(robot => { robot.eyes.forEach(eye => { eye.classList.add('sparkle', 'rainbow'); }); this.showSpeechBubble(robot, "Secret mode activated! 🎉"); }); // Remove after 5 seconds setTimeout(() => { this.robots.forEach(robot => { robot.eyes.forEach(eye => { eye.classList.remove('sparkle', 'rainbow'); }); }); }, 5000); } handleKeyPress(e) { // Number keys change robot expressions if (e.key >= '1' && e.key <= '9') { const expressions = ['happy', 'sad', 'surprised', 'angry', 'love', 'sleepy', 'wink', 'dizzy', 'cool']; const expression = expressions[parseInt(e.key) - 1]; if (expression) { this.robots.forEach(robot => { this.setRobotExpression(robot, expression); }); } } } setRobotExpression(robot, expression) { // Clear previous expressions const allExpressions = ['happy', 'sad', 'surprised', 'angry', 'love', 'sleepy', 'wink', 'dizzy', 'cool']; robot.eyes.forEach(eye => { allExpressions.forEach(exp => eye.classList.remove(exp)); eye.classList.add(expression); }); // Remove after 3 seconds setTimeout(() => { robot.eyes.forEach(eye => { eye.classList.remove(expression); }); }, 3000); } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { window.robotInteractions = new RobotInteractions(); window.robotInteractions.init(); }); } else { window.robotInteractions = new RobotInteractions(); window.robotInteractions.init(); } // Add required styles dynamically const style = document.createElement('style'); style.textContent = ` /* Pupil for eye tracking */ .robot-eye .pupil { position: absolute; top: 50%; left: 50%; width: 40%; height: 40%; background: white; border-radius: 50%; transform: translate(-50%, -50%); transition: transform 0.1s ease-out; pointer-events: none; } /* Speech bubble */ .robot-speech-bubble { position: absolute; bottom: 110%; left: 50%; transform: translateX(-50%); background: white; color: #1A1A2E; padding: 0.75rem 1rem; border-radius: 20px; border: 3px solid #1A1A2E; font-size: 0.9rem; font-weight: 600; white-space: nowrap; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); animation: bubbleIn 0.3s ease-out; z-index: 100; } .robot-speech-bubble.fade-out { animation: bubbleOut 0.3s ease-in forwards; } .bubble-tail { position: absolute; bottom: -8px; left: 50%; transform: translateX(-50%); width: 0; height: 0; border-left: 8px solid transparent; border-right: 8px solid transparent; border-top: 10px solid white; } .bubble-tail::before { content: ''; position: absolute; bottom: 2px; left: -10px; width: 0; height: 0; border-left: 10px solid transparent; border-right: 10px solid transparent; border-top: 12px solid #1A1A2E; } /* Thinking bubbles */ .thinking-bubbles { position: absolute; top: -40px; right: -20px; animation: bubbleFloat 3s ease-in-out; } .thinking-bubbles.fade-out { animation: fadeOut 0.3s ease-in forwards; } .think-bubble { position: absolute; background: white; border: 2px solid #1A1A2E; border-radius: 50%; } .think-bubble.small { width: 8px; height: 8px; bottom: 0; left: 0; } .think-bubble.medium { width: 12px; height: 12px; bottom: 10px; left: -5px; } .think-bubble.large { width: 30px; height: 30px; bottom: 25px; left: -15px; display: flex; align-items: center; justify-content: center; font-size: 16px; } /* Big smile animation */ .robot-smile.big-smile { width: 30px !important; height: 15px !important; border-width: 4px !important; } /* Dance animations */ @keyframes robot-wiggle { 0%, 100% { transform: rotate(-5deg); } 50% { transform: rotate(5deg); } } @keyframes robot-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes robot-bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-20px); } } @keyframes robot-shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } } @keyframes robotJump { 0%, 100% { transform: translateY(0) scale(1); } 50% { transform: translateY(-30px) scale(1.1); } } @keyframes bubbleIn { 0% { opacity: 0; transform: translateX(-50%) scale(0.8); } 100% { opacity: 1; transform: translateX(-50%) scale(1); } } @keyframes bubbleOut { 0% { opacity: 1; transform: translateX(-50%) scale(1); } 100% { opacity: 0; transform: translateX(-50%) scale(0.8); } } @keyframes fadeOut { 0% { opacity: 1; } 100% { opacity: 0; } } @keyframes bubbleFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } } /* Disco mode */ .disco-lights { position: fixed; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; z-index: 9999; } .disco-ball { position: absolute; top: 50px; left: 50%; transform: translateX(-50%); font-size: 60px; animation: discoSpin 2s linear infinite; } .light-beam { position: absolute; top: 100px; left: 50%; width: 100px; height: 500px; opacity: 0.3; transform-origin: top center; animation: lightSweep 4s ease-in-out infinite; } .light-beam.red { background: linear-gradient(transparent, #FF006E); } .light-beam.blue { background: linear-gradient(transparent, #3A86FF); animation-delay: 1s; } .light-beam.green { background: linear-gradient(transparent, #06FFA5); animation-delay: 2s; } .light-beam.yellow { background: linear-gradient(transparent, #FFB700); animation-delay: 3s; } @keyframes discoSpin { 0% { transform: translateX(-50%) rotate(0deg); } 100% { transform: translateX(-50%) rotate(360deg); } } @keyframes lightSweep { 0%, 100% { transform: translateX(-50%) rotate(-30deg); } 50% { transform: translateX(-50%) rotate(30deg); } } /* Rainbow eyes */ .robot-eye.rainbow { animation: rainbowEyes 2s linear infinite; } @keyframes rainbowEyes { 0% { background: #FF006E; } 25% { background: #3A86FF; } 50% { background: #06FFA5; } 75% { background: #FFB700; } 100% { background: #FF006E; } } /* Sparkle effect */ .robot-eye.sparkle::before { content: '✨'; position: absolute; top: -10px; right: -10px; font-size: 12px; animation: sparkleFloat 1s ease-in-out infinite; } @keyframes sparkleFloat { 0%, 100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-5px) rotate(180deg); } } `; document.head.appendChild(style);