🎯 Цель урока
Превращаем нашу игру в визуальный праздник! Добавляем анимации, эффекты частиц, интерактивные переходы и профессиональную полировку.
Ты научишься создавать современные анимации, которые делают пользовательский интерфейс живым и увлекательным.
Демонстрация анимаций
Дрожание при поражении
Прыжок при победе
Пульсация ожидания
Вращение загрузки
Свечение выбора
Парение в воздухе
🎨 CSS Keyframes анимации
CSS @keyframes позволяют создавать сложные анимации. Определяем ключевые точки и браузер плавно интерполирует между ними.
/* Дрожание при ошибке */ @keyframes shake { 0% { transform: translateX(-5px); } 25% { transform: translateX(5px); } 50% { transform: translateX(-5px); } 75% { transform: translateX(5px); } 100% { transform: translateX(0); } } /* Пульсация при ожидании */ @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.1); opacity: 0.7; } } /* Свечение для выделения */ @keyframes glow { 0% { box-shadow: 0 0 10px #667eea; } 100% { box-shadow: 0 0 30px #667eea, 0 0 40px #667eea; } } /* Применение анимаций */ .choice-button.shake { animation: shake 0.5s ease-out; } .choice-button.waiting { animation: pulse 1.5s infinite; } .choice-button.selected { animation: glow 2s infinite alternate; }
🎪 Эффекты для результатов игры
Создадим специальные анимации для разных исходов: победа, поражение, ничья. Каждый результат получит уникальный визуальный фидбек.
/* Анимация победы - увеличение и зелёный цвет */ @keyframes winPulse { 0% { transform: scale(1); background: linear-gradient(135deg, #667eea, #764ba2); } 50% { transform: scale(1.2); background: linear-gradient(135deg, #2ecc71, #27ae60); } 100% { transform: scale(1); background: linear-gradient(135deg, #667eea, #764ba2); } } /* Анимация поражения - уменьшение и красный цвет */ @keyframes loseFade { 0% { transform: scale(1); background: linear-gradient(135deg, #667eea, #764ba2); opacity: 1; } 50% { transform: scale(0.9); background: linear-gradient(135deg, #e74c3c, #c0392b); opacity: 0.7; } 100% { transform: scale(1); background: linear-gradient(135deg, #667eea, #764ba2); opacity: 1; } } /* Встряхивание всего экрана при критическом поражении */ @keyframes screenShake { 0%, 100% { transform: translateX(0); } 10% { transform: translateX(-10px); } 20% { transform: translateX(10px); } 30% { transform: translateX(-10px); } 40% { transform: translateX(10px); } }
⭐ JavaScript анимации и эффекты
Используем JavaScript для создания динамических эффектов: частиц, конфетти, плавных переходов и интерактивных анимаций.
// Система управления анимациями const AnimationSystem = { // Применить анимацию к элементу applyAnimation(element, animationClass, duration = 1000) { element.classList.add(animationClass); setTimeout(() => { element.classList.remove(animationClass); }, duration); }, // Эффект победы для кнопки winEffect(buttonElement) { this.applyAnimation(buttonElement, 'animate-win', 1000); this.createConfetti(buttonElement); }, // Эффект поражения loseEffect(buttonElement) { this.applyAnimation(buttonElement, 'animate-lose', 1000); this.shakeScreen(); }, // Встряхивание экрана shakeScreen() { const gameContainer = document.querySelector('.game-container'); this.applyAnimation(gameContainer, 'screen-shake', 500); }, // Создание конфетти createConfetti(centerElement) { const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff']; const container = document.body; for (let i = 0; i < 20; i++) { const confetti = document.createElement('div'); confetti.className = 'confetti'; confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; confetti.style.left = Math.random() * 100 + 'vw'; confetti.style.animationDelay = Math.random() * 2 + 's'; container.appendChild(confetti); // Удаляем элемент после анимации setTimeout(() => { container.removeChild(confetti); }, 3000); } } };
Интерактивная демонстрация
Нажми на кнопки, чтобы увидеть анимации в действии:
Левая кнопка - победа, средняя - поражение, правая - ничья
🌟 Эффекты частиц
Частицы добавляют профессионализм игре. Создадим систему для генерации искр, дыма, звёзд и других визуальных эффектов.
// Система частиц const ParticleSystem = { particles: [], // Создать частицу createParticle(x, y, type = 'spark') { const particle = { x: x, y: y, vx: (Math.random() - 0.5) * 10, // Скорость по X vy: (Math.random() - 0.5) * 10, // Скорость по Y life: 1.0, // Жизнь частицы (0-1) decay: Math.random() * 0.02 + 0.01, // Скорость затухания type: type, size: Math.random() * 5 + 2, // Размер color: this.getParticleColor(type) }; this.particles.push(particle); }, // Цвета для разных типов частиц getParticleColor(type) { const colors = { spark: '#ffd700', // Золотые искры smoke: '#888888', // Серый дым magic: '#9b59b6', // Фиолетовая магия fire: '#ff4500' // Оранжевый огонь }; return colors[type] || colors.spark; }, // Обновление всех частиц update() { for (let i = this.particles.length - 1; i >= 0; i--) { const p = this.particles[i]; // Обновляем позицию p.x += p.vx; p.y += p.vy; // Гравитация p.vy += 0.3; // Затухание p.life -= p.decay; // Удаляем "мёртвые" частицы if (p.life <= 0) { this.particles.splice(i, 1); } } }, // Эффект взрыва искр sparkExplosion(x, y, count = 15) { for (let i = 0; i < count; i++) { this.createParticle(x, y, 'spark'); } } };
📝 Текстовые эффекты
Анимированный текст делает интерфейс более живым:
Печатающийся текст
Радужный текст
Глитч эффект
🎭 Интеграция анимаций в игру
Теперь подключим все анимации к основной логике игры. Каждое действие игрока будет сопровождаться визуальным фидбеком.
// Обновлённая функция игры с анимациями function makeChoiceAnimated(playerChoice) { const playerButton = document.querySelector(`[data-choice="${playerChoice}"]`); const resultElement = document.getElementById('gameResult'); // 1. Анимация выбора игрока AnimationSystem.applyAnimation(playerButton, 'selected', 500); // 2. Показываем индикатор загрузки resultElement.textContent = 'Компьютер думает...'; AnimationSystem.applyAnimation(resultElement, 'pulse', 1500); // 3. Задержка для драматизма setTimeout(() => { const computerChoice = AISystem.getChoice(); const result = determineWinner(playerChoice, computerChoice); // 4. Показываем результат с анимацией displayResult(result, playerChoice, computerChoice); // 5. Применяем соответствующую анимацию switch (result) { case 'win': AnimationSystem.winEffect(playerButton); ParticleSystem.sparkExplosion( playerButton.offsetLeft + playerButton.offsetWidth / 2, playerButton.offsetTop + playerButton.offsetHeight / 2 ); break; case 'lose': AnimationSystem.loseEffect(playerButton); break; case 'draw': AnimationSystem.applyAnimation(playerButton, 'pulse', 1000); break; } // 6. Обновляем статистику с анимацией updateStatsAnimated(result); }, 1000); } // Анимированное обновление статистики function updateStatsAnimated(result) { updateStats(result); // Обычное обновление // Анимация изменившихся счётчиков const statElements = { wins: document.getElementById('wins'), losses: document.getElementById('losses'), draws: document.getElementById('draws'), streak: document.getElementById('streak') }; switch (result) { case 'win': AnimationSystem.applyAnimation(statElements.wins, 'bounce', 600); AnimationSystem.applyAnimation(statElements.streak, 'glow', 1000); break; case 'lose': AnimationSystem.applyAnimation(statElements.losses, 'shake', 500); break; case 'draw': AnimationSystem.applyAnimation(statElements.draws, 'pulse', 800); break; } }
✨ Твоё задание
Добавь анимационные эффекты в свою игру:
- Создай CSS @keyframes для основных анимаций (shake, pulse, glow, bounce)
- Реализуй систему управления анимациями через JavaScript
- Добавь анимации для каждого результата игры (победа, поражение, ничья)
- Создай эффект частиц для особых моментов
- Интегрируй анимации в основную логику игры
- Добавь анимированное обновление статистики
- Создай текстовые эффекты для результатов
- Протестируй все анимации на разных устройствах
💡 Не переборщи с анимациями - они должны улучшать, а не отвлекать!