🎯 Цель урока
В финальном уроке мы добавим систему сохранения прогресса, чтобы питомец "помнил" игрока даже после закрытия браузера. Также отполируем интерфейс, добавим звуковые эффекты и финальные штрихи для профессионального вида.
Ты освоишь localStorage для сохранения данных, научишься создавать полноценные веб-приложения с персистентным состоянием и профессиональной полировкой.
Демонстрация localStorage
Попробуй сохранить и загрузить данные прямо сейчас!
💾 Основы localStorage
localStorage позволяет сохранять данные в браузере пользователя. Данные остаются даже после закрытия браузера и перезагрузки компьютера.
// Сохраняем данные localStorage.setItem('ключ', 'значение'); // Получаем данные const data = localStorage.getItem('ключ'); // Удаляем данные localStorage.removeItem('ключ'); // Очищаем весь localStorage localStorage.clear(); // Проверяем, есть ли данные if (localStorage.getItem('ключ') !== null) { // Данные существуют } // Сохранение объектов (нужно преобразовать в JSON) const myObject = { name: "Питомец", level: 5 }; localStorage.setItem('pet', JSON.stringify(myObject)); // Загрузка объектов const savedPet = JSON.parse(localStorage.getItem('pet'));
JSON.stringify() превращает объект в строку, а JSON.parse() обратно в объект.
💾 Функции сохранения питомца
Создадим функции для сохранения всего состояния нашего тамагочи: статистики, уровень, достижения, возраст и стадию развития.
// Ключ для сохранения данных const SAVE_KEY = 'tamagochi_save_data'; // Функция сохранения всех данных function saveGame() { try { // Создаём объект с данными для сохранения const saveData = { pet: { name: pet.name, level: pet.level, age: pet.age, stage: pet.stage, emoji: pet.emoji, stats: { ...pet.stats }, // Копируем статистики status: pet.status, lastFed: pet.lastFed, isAlive: pet.isAlive, intelligence: pet.intelligence || 0, experience: pet.experience || 0 }, achievements: { ...achievements }, // Копируем достижения gameStats: { totalActions: gameStats.totalActions || 0, gamesPlayed: gameStats.gamesPlayed || 0, evolutionsCount: gameStats.evolutionsCount || 0 }, saveDate: new Date().toISOString(), version: "1.0" // На случай будущих обновлений }; // Сохраняем в localStorage localStorage.setItem(SAVE_KEY, JSON.stringify(saveData)); showMessage("💾 Игра сохранена успешно!"); showSaveAnimation(); return true; } catch (error) { console.error("Ошибка сохранения:", error); showMessage("❌ Ошибка при сохранении!"); return false; } } // Функция загрузки данных function loadGame() { try { const savedData = localStorage.getItem(SAVE_KEY); if (!savedData) { showMessage("📁 Сохранённых данных не найдено"); return false; } const saveData = JSON.parse(savedData); // Проверяем версию сохранения if (!saveData.version) { showMessage("⚠️ Старая версия сохранения!"); } // Загружаем данные питомца pet.name = saveData.pet.name; pet.level = saveData.pet.level; pet.age = saveData.pet.age; pet.stage = saveData.pet.stage; pet.emoji = saveData.pet.emoji; pet.stats = { ...saveData.pet.stats }; pet.status = saveData.pet.status; pet.lastFed = saveData.pet.lastFed; pet.isAlive = saveData.pet.isAlive; pet.intelligence = saveData.pet.intelligence || 0; pet.experience = saveData.pet.experience || 0; // Загружаем достижения Object.assign(achievements, saveData.achievements); // Загружаем игровую статистику if (saveData.gameStats) { gameStats = { ...saveData.gameStats }; } // Обновляем интерфейс updateDisplay(); updateAchievementsDisplay(); const saveDate = new Date(saveData.saveDate).toLocaleString(); showMessage(`📁 Игра загружена! Сохранено: ${saveDate}`); return true; } catch (error) { console.error("Ошибка загрузки:", error); showMessage("❌ Ошибка при загрузке!"); return false; } }
⚙️ Автосохранение
Добавим автоматическое сохранение каждые несколько минут, чтобы игрок не потерял прогресс, если забудет сохраниться вручную.
// Настройки автосохранения const AUTOSAVE_INTERVAL = 3 * 60 * 1000; // 3 минуты в миллисекундах let autosaveTimer = null; let gameModified = false; // Флаг изменений // Запуск автосохранения function startAutosave() { if (autosaveTimer) { clearInterval(autosaveTimer); } autosaveTimer = setInterval(() => { if (gameModified && pet.isAlive) { saveGame(); gameModified = false; console.log("Автосохранение выполнено"); } }, AUTOSAVE_INTERVAL); } // Остановка автосохранения function stopAutosave() { if (autosaveTimer) { clearInterval(autosaveTimer); autosaveTimer = null; } } // Функция для отметки изменений function markGameModified() { gameModified = true; } // Автозагрузка при старте игры function initializeGame() { // Пытаемся загрузить сохранённые данные if (localStorage.getItem(SAVE_KEY)) { const userWantsLoad = confirm("Найдено сохранение! Загрузить игру?"); if (userWantsLoad) { loadGame(); } } // Запускаем автосохранение startAutosave(); // Запускаем главный игровой цикл startGameLoop(); } // Сохранение при закрытии страницы window.addEventListener('beforeunload', (event) => { if (gameModified && pet.isAlive) { saveGame(); } });
🔄 Функция сброса игры
Иногда игроку может понадобиться начать заново. Создадим безопасную функцию сброса с подтверждением действия.
function resetGame() { // Двойное подтверждение для безопасности const firstConfirm = confirm( "⚠️ Вы уверены, что хотите начать заново?\nВесь прогресс будет потерян!" ); if (!firstConfirm) return; const secondConfirm = confirm( "🚨 ПОСЛЕДНЕЕ ПРЕДУПРЕЖДЕНИЕ!\nЭто действие нельзя отменить. Продолжить?" ); if (!secondConfirm) return; // Останавливаем все процессы stopAutosave(); stopGameLoop(); // Очищаем localStorage localStorage.removeItem(SAVE_KEY); // Сбрасываем объект питомца к начальным значениям pet = { name: "Малыш", level: 1, age: 0, stage: "egg", emoji: "🥚", stats: { hunger: 100, happiness: 100, energy: 100, cleanliness: 100 }, status: "Спокоен", lastFed: Date.now(), isAlive: true, intelligence: 0, experience: 0 }; // Сбрасываем достижения Object.keys(achievements).forEach(key => { achievements[key].unlocked = false; if (achievements[key].current !== undefined) { achievements[key].current = 0; } }); // Сбрасываем игровую статистику gameStats = { totalActions: 0, gamesPlayed: 0, evolutionsCount: 0 }; // Обновляем интерфейс updateDisplay(); updateAchievementsDisplay(); // Перезапускаем игру initializeGame(); showMessage("🔄 Игра сброшена! Добро пожаловать снова!"); }
Звуковые эффекты
Добавь звуки кормления, игр и эволюции для большей погружённости
Мобильная адаптация
Оптимизируй интерфейс для телефонов и планшетов
Темы оформления
Создай разные цветовые темы на выбор игрока
Статистика игры
Покажи статистику: время игры, количество действий, рекорды
Дополнительные достижения
Добавь больше достижений для долгосрочной мотивации
Система подарков
Случайные подарки за хороший уход повышают интерес
✨ Финальные улучшения
Небольшие детали делают игру профессиональной. Добавим уведомления, улучшенную анимацию и обработку ошибок.
// Красивые уведомления function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.textContent = message; document.body.appendChild(notification); // Анимация появления setTimeout(() => { notification.classList.add('show'); }, 100); // Автоматическое исчезновение setTimeout(() => { notification.classList.add('hide'); setTimeout(() => { notification.remove(); }, 300); }, 3000); } // Анимация сохранения function showSaveAnimation() { const saveIcon = document.createElement('div'); saveIcon.className = 'save-animation'; saveIcon.textContent = '💾'; document.body.appendChild(saveIcon); setTimeout(() => { saveIcon.remove(); }, 2000); } // Обработка ошибок window.addEventListener('error', (event) => { console.error('Ошибка игры:', event.error); showNotification('Произошла ошибка! Попробуйте перезагрузить страницу.', 'error'); }); // Проверка поддержки localStorage function checkLocalStorageSupport() { try { const test = 'test'; localStorage.setItem(test, test); localStorage.removeItem(test); return true; } catch (e) { showNotification('Ваш браузер не поддерживает сохранения!', 'warning'); return false; } }
💾 Твоё задание
Добавь систему сохранения и финальную полировку:
- Функции saveGame() и loadGame() с обработкой ошибок
- Автосохранение каждые 3 минуты
- Автозагрузку при запуске игры с подтверждением
- Безопасную функцию сброса игры
- Сохранение при закрытии браузера
- Красивые уведомления для важных событий
- Проверку поддержки localStorage
- CSS анимации для улучшения UX
💡 Тестируй сохранения в разных браузерах и устройствах!
🎉 Поздравляем!
Ты создал полнофункционального виртуального питомца!
Твой тамагочи умеет:
- 🍎 Есть и поддерживать здоровье
- 🎮 Играть и развивать интеллект
- 🌱 Эволюционировать через 5 стадий
- 🧠 Играть в мини-игры на память
- 🏆 Зарабатывать достижения
- 💾 Сохранять прогресс навсегда
- ✨ Реагировать на твою заботу