← Вернуться к урокам

✨ Финальные улучшения

Урок 5 из 5

🎯 Цель урока

В этом финальном уроке мы добавим последние штрихи к нашей игре: визуальные эффекты с частицами, кнопку сброса, звуковые эффекты и сделаем игру ещё более впечатляющей!

💡 Что вы узнаете:

• Создание анимированных частиц
• Добавление кнопки сброса
• Работа со звуками (основы)
• Финальная оптимизация кода
• Создание полноценной игры

📚 Новые концепции

createElement()

Создаёт новый HTML элемент в JavaScript, который можно добавить на страницу.

appendChild()

Добавляет созданный элемент как дочерний элемент к другому элементу.

removeChild()

Удаляет элемент из DOM (Document Object Model).

CSS Animations

CSS анимации через @keyframes для создания плавных визуальных эффектов.

Audio API

Базовая работа со звуками в браузере (воспроизведение звуковых эффектов).

🛠️ Финальная версия игры

Вот полный код нашей улучшенной игры:

<!DOCTYPE html>
<html lang="ru">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Волшебная кнопка - Финальная версия</title>
    <style>
      body {
        font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        margin: 0;
        padding: 0;
        min-height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
        color: white;
      }

      .game-container {
        text-align: center;
        background: rgba(255, 255, 255, 0.1);
        backdrop-filter: blur(10px);
        border-radius: 20px;
        padding: 40px;
        border: 1px solid rgba(255, 255, 255, 0.2);
        box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
        position: relative;
        overflow: hidden;
        max-width: 500px;
      }

      .magic-button {
        background: linear-gradient(135deg, #ff6b6b, #ffa500);
        color: white;
        border: none;
        padding: 20px 40px;
        font-size: 1.5rem;
        font-weight: bold;
        border-radius: 50px;
        cursor: pointer;
        transition: all 0.3s ease;
        box-shadow: 0 8px 25px rgba(255, 107, 107, 0.3);
        position: relative;
        z-index: 2;
      }

      .magic-button:hover {
        transform: translateY(-5px);
        box-shadow: 0 15px 35px rgba(255, 107, 107, 0.4);
      }

      .magic-button.clicked {
        transform: scale(1.1) translateY(-5px);
        box-shadow: 0 20px 40px rgba(255, 107, 107, 0.6);
      }

      .reset-button {
        background: linear-gradient(135deg, #6c757d, #495057);
        color: white;
        border: none;
        padding: 10px 20px;
        font-size: 1rem;
        font-weight: 600;
        border-radius: 25px;
        cursor: pointer;
        transition: all 0.3s ease;
        margin-top: 20px;
      }

      .reset-button:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 20px rgba(108, 117, 125, 0.3);
      }

      .click-counter {
        font-size: 1.8rem;
        font-weight: bold;
        margin: 20px 0;
        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
      }

      .particles {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        pointer-events: none;
        z-index: 1;
      }

      .particle {
        position: absolute;
        font-size: 1.5rem;
        animation: particleFloat 2s ease-out forwards;
        pointer-events: none;
      }

      @keyframes particleFloat {
        0% {
          opacity: 1;
          transform: translateY(0) scale(1) rotate(0deg);
        }
        100% {
          opacity: 0;
          transform: translateY(-100px) scale(0.5) rotate(360deg);
        }
      }

      .achievement {
        background: linear-gradient(135deg, #ffd700, #ffed4e);
        color: #8b4513;
        padding: 15px;
        border-radius: 15px;
        margin-top: 20px;
        font-weight: bold;
        border: 2px solid #ffc107;
        animation: achievementPulse 0.5s ease-in-out;
      }

      @keyframes achievementPulse {
        0%, 100% { transform: scale(1); }
        50% { transform: scale(1.05); }
      }
    </style>
  </head>
  <body>
    <div class="game-container">
      <div class="particles" id="particles"></div>
      <h1>🪄 Волшебная кнопка</h1>
      <div id="clickCounter" class="click-counter">Кликов: 0</div>
      <p>Нажми на кнопку и увидишь магию!</p>
      <button class="magic-button" onclick="showMagic()">✨ Магия! ✨</button>
      <div id="magicMessage"></div>
      <div id="achievements"></div>
      <button class="reset-button" onclick="resetGame()">🔄 Начать сначала</button>
    </div>

    <script>
      let clickCount = 0;
      
      const magicMessages = [
        "🎉 Вау! Это действительно магия! 🎉",
        "✨ Звёзды танцуют в небе! ✨",
        "🌟 Ты призвал магическую силу! 🌟",
        "🎨 Радуга появилась из ниоткуда! 🎨",
        "🦄 Единорог мелькнул где-то рядом! 🦄",
        "🎪 Магический цирк открыт! 🎪",
        "🌙 Луна улыбается тебе! 🌙",
        "⭐ Падающая звезда исполняет желания! ⭐"
      ];

      const particleEmojis = ["✨", "🌟", "💫", "⭐", "🎆", "🎇", "💥", "🔮"];

      function showMagic() {
        clickCount++;
        
        // Обновляем счётчик
        document.getElementById('clickCounter').innerHTML = `Кликов: ${clickCount}`;
        
        // Создаём частицы
        createParticles();
        
        // Проверяем достижения
        checkAchievements();
        
        // Показываем сообщение
        showRandomMessage();
        
        // Анимация кнопки
        animateButton();
        
        // Воспроизводим звук (если доступен)
        playClickSound();
      }

      function createParticles() {
        const particleContainer = document.getElementById('particles');
        
        // Создаём 5-8 случайных частиц
        const particleCount = 5 + Math.floor(Math.random() * 4);
        
        for (let i = 0; i < particleCount; i++) {
          const particle = document.createElement('div');
          particle.className = 'particle';
          particle.innerHTML = particleEmojis[Math.floor(Math.random() * particleEmojis.length)];
          
          // Случайная позиция
          particle.style.left = Math.random() * 100 + '%';
          particle.style.top = Math.random() * 100 + '%';
          
          // Случайная задержка анимации
          particle.style.animationDelay = Math.random() * 0.5 + 's';
          
          particleContainer.appendChild(particle);
          
          // Удаляем частицу через 2.5 секунды
          setTimeout(() => {
            if (particle.parentNode) {
              particle.parentNode.removeChild(particle);
            }
          }, 2500);
        }
      }

      function showRandomMessage() {
        const randomIndex = Math.floor(Math.random() * magicMessages.length);
        const randomMessage = magicMessages[randomIndex];
        
        const messageElement = document.getElementById('magicMessage');
        messageElement.innerHTML = `<p style="margin-top: 20px; font-size: 1.2rem; animation: fadeIn 0.5s ease-in;">${randomMessage}</p>`;
        
        setTimeout(() => {
          messageElement.innerHTML = '';
        }, 3000);
      }

      function animateButton() {
        const button = document.querySelector('.magic-button');
        button.classList.add('clicked');
        
        setTimeout(() => {
          button.classList.remove('clicked');
        }, 200);
      }

      function checkAchievements() {
        const achievementContainer = document.getElementById('achievements');
        let achievement = '';
        
        switch(clickCount) {
          case 5:
            achievement = '🏆 Первые шаги в магии!';
            break;
          case 10:
            achievement = '🌟 Юный волшебник!';
            break;
          case 25:
            achievement = '🔮 Опытный маг!';
            break;
          case 50:
            achievement = '🧙‍♂️ Мастер магии!';
            break;
          case 100:
            achievement = '👑 ЛЕГЕНДА МАГИИ!';
            break;
        }
        
        if (achievement) {
          achievementContainer.innerHTML = `<div class="achievement">${achievement}</div>`;
          
          setTimeout(() => {
            achievementContainer.innerHTML = '';
          }, 5000);
        }
      }

      function playClickSound() {
        // Простой звук клика (если браузер поддерживает)
        try {
          const audioContext = new (window.AudioContext || window.webkitAudioContext)();
          const oscillator = audioContext.createOscillator();
          const gainNode = audioContext.createGain();
          
          oscillator.connect(gainNode);
          gainNode.connect(audioContext.destination);
          
          oscillator.frequency.setValueAtTime(800, audioContext.currentTime);
          oscillator.frequency.exponentialRampToValueAtTime(400, audioContext.currentTime + 0.1);
          
          gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
          gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.1);
          
          oscillator.start(audioContext.currentTime);
          oscillator.stop(audioContext.currentTime + 0.1);
        } catch (e) {
          // Звук не поддерживается - ничего страшного
        }
      }

      function resetGame() {
        clickCount = 0;
        document.getElementById('clickCounter').innerHTML = 'Кликов: 0';
        document.getElementById('magicMessage').innerHTML = '';
        document.getElementById('achievements').innerHTML = '';
        
        // Очищаем частицы
        const particleContainer = document.getElementById('particles');
        particleContainer.innerHTML = '';
        
        // Показываем сообщение о сбросе
        const messageElement = document.getElementById('magicMessage');
        messageElement.innerHTML = '<p style="margin-top: 20px; font-size: 1.2rem; color: #ffd700;">🔄 Игра сброшена! Начинаем заново! 🔄</p>';
        
        setTimeout(() => {
          messageElement.innerHTML = '';
        }, 2000);
      }

      // Добавляем CSS анимацию для сообщений
      const style = document.createElement('style');
      style.textContent = `
        @keyframes fadeIn {
          from { opacity: 0; transform: translateY(10px); }
          to { opacity: 1; transform: translateY(0); }
        }
      `;
      document.head.appendChild(style);
    </script>
  </body>
</html>

🎮 Попробуйте финальную версию!

Вот как выглядит наша полностью готовая игра:

🪄 Волшебная кнопка

Кликов: 0

Нажми на кнопку и увидишь магию!

🔧 Объяснение новых функций

1. Система частиц:

function createParticles() {
  const particleContainer = document.getElementById('particles');
  const particleCount = 5 + Math.floor(Math.random() * 4);
  
  for (let i = 0; i < particleCount; i++) {
    const particle = document.createElement('div');
    particle.className = 'particle';
    particle.innerHTML = particleEmojis[Math.floor(Math.random() * particleEmojis.length)];
    
    particle.style.left = Math.random() * 100 + '%';
    particle.style.top = Math.random() * 100 + '%';
    
    particleContainer.appendChild(particle);
  }
}

2. Система достижений:

Проверяет количество кликов и показывает особые сообщения при достижении определённых целей.

3. Кнопка сброса:

Обнуляет все счётчики и очищает экран, позволяя начать игру заново.

4. Звуковые эффекты:

Использует Web Audio API для создания простых звуков клика (работает не во всех браузерах).

🎊 Поздравляем!

Вы успешно создали свою первую интерактивную игру!

Теперь у вас есть:

  • ✅ Красивая HTML структура
  • ✅ Стильная CSS анимация
  • ✅ Интерактивный JavaScript
  • ✅ Система счётчика
  • ✅ Визуальные эффекты
  • ✅ Система достижений
  • ✅ Полноценная игра!

🎓 Что вы изучили за весь курс

  • HTML: Структура веб-страниц, теги, атрибуты
  • CSS: Стилизация, градиенты, анимации, переходы
  • JavaScript: Переменные, функции, события, DOM
  • Интерактивность: Обработка кликов, изменение содержимого
  • Анимации: CSS анимации, динамические эффекты
  • Игровая логика: Счётчики, случайность, достижения
  • Пользовательский опыт: Визуальная обратная связь, звуки

🚀 Что дальше?

Теперь вы можете:
• Изменить дизайн и цвета игры
• Добавить новые типы сообщений
• Создать другие мини-игры
• Изучить более сложные возможности JavaScript
• Поделиться своей игрой с друзьями!