← Назад к курсу

🏆 Урок 5a: Система достижений

Создаём мотивирующую систему наград и очков

🎯 Цель урока

В этом уроке мы создадим увлекательную систему достижений для игры "Угадай число". Изучим, как мотивировать игроков через награды, очки и прогресс.

Ты узнаешь, как правильно спроектировать систему достижений, которая будет мотивировать игроков возвращаться и улучшать свои результаты.

🎖️ Интерактивная система достижений

Попробуй разблокировать достижения:

0
Очки
0
Игр
0
Побед
0
Серия

🏆 Типы достижений

Хорошая система достижений включает разнообразные цели, которые подходят для разных типов игроков и стилей игры.

🎨 Категории достижений

🎯
Точность
За угадывание с минимальным количеством попыток
🔥
Серии побед
За последовательные победы без поражений
📊
Статистика
За общие показатели: количество игр, побед
Скорость
За быстрое угадывание чисел
🧠
Стратегия
За использование оптимальных алгоритмов
💎
Редкие
Особые достижения для мастеров игры
🏆 Структура достижений
// Конфигурация системы достижений
const ACHIEVEMENTS = {
    // Достижения точности
    accuracy: {
        perfectGuess: {
            id: 'perfect-guess',
            name: '🎯 Снайпер',
            description: 'Угадай число с первой попытки',
            condition: (stats) => stats.lastGameAttempts === 1,
            points: 100,
            rarity: 'legendary'
        },
        sharpshooter: {
            id: 'sharpshooter',
            name: '🏹 Меткий стрелок',
            description: 'Угадай число за 3 попытки или меньше',
            condition: (stats) => stats.lastGameAttempts <= 3 && stats.lastGameAttempts > 1,
            points: 50,
            rarity: 'epic'
        },
        efficient: {
            id: 'efficient',
            name: '⚡ Эффективный',
            description: 'Угадай число за 5 попыток или меньше',
            condition: (stats) => stats.lastGameAttempts <= 5,
            points: 25,
            rarity: 'rare'
        }
    },
    
    // Серии побед
    streaks: {
        hotStreak: {
            id: 'hot-streak',
            name: '🔥 Горячая серия',
            description: 'Выиграй 3 игры подряд',
            condition: (stats) => stats.winStreak >= 3,
            points: 75,
            rarity: 'epic'
        },
        unstoppable: {
            id: 'unstoppable',
            name: '🚀 Неудержимый',
            description: 'Выиграй 5 игр подряд',
            condition: (stats) => stats.winStreak >= 5,
            points: 150,
            rarity: 'legendary'
        },
        champion: {
            id: 'champion',
            name: '👑 Чемпион',
            description: 'Выиграй 10 игр подряд',
            condition: (stats) => stats.winStreak >= 10,
            points: 500,
            rarity: 'mythic'
        }
    },
    
    // Статистические достижения
    milestones: {
        firstWin: {
            id: 'first-win',
            name: '🌟 Первая победа',
            description: 'Выиграй свою первую игру',
            condition: (stats) => stats.totalWins === 1,
            points: 20,
            rarity: 'common'
        },
        veteran: {
            id: 'veteran',
            name: '🎖️ Ветеран',
            description: 'Сыграй 25 игр',
            condition: (stats) => stats.totalGames >= 25,
            points: 100,
            rarity: 'rare'
        },
        master: {
            id: 'master',
            name: '🏆 Мастер',
            description: 'Выиграй 50 игр',
            condition: (stats) => stats.totalWins >= 50,
            points: 300,
            rarity: 'legendary'
        }
    }
};

// Редкость достижений
const RARITY_CONFIG = {
    common: { color: '#95a5a6', multiplier: 1 },
    rare: { color: '#3498db', multiplier: 1.5 },
    epic: { color: '#9b59b6', multiplier: 2 },
    legendary: { color: '#f39c12', multiplier: 3 },
    mythic: { color: '#e74c3c', multiplier: 5 }
};

Каждое достижение имеет условие проверки, количество очков и редкость, которая влияет на ценность награды.

💰 Система очков

Очки мотивируют игроков и показывают прогресс:

Действие Базовые очки Бонус за сложность Итого
Победа (лёгкий) +10 ×1.0 10
Победа (средний) +10 ×1.5 15
Победа (сложный) +10 ×2.0 20
Победа (экстрим) +10 ×3.0 30
Быстрая победа (≤3 попытки) +25 ×1.5 37.5
Идеальная игра (1 попытка) +100 ×2.0 200
💰 Расчёт очков
// Система подсчёта очков
class ScoreSystem {
    constructor() {
        this.basePoints = {
            win: 10,
            quickWin: 25,        // ≤ 3 попытки
            perfectGame: 100,    // 1 попытка
            streakBonus: 5,      // за каждую игру в серии
            difficultyBonus: 10  // за каждый уровень сложности
        };
        
        this.difficultyMultipliers = {
            easy: 1.0,
            medium: 1.5,
            hard: 2.0,
            extreme: 3.0
        };
    }
    
    // Вычисляем очки за игру
    calculateGameScore(gameResult) {
        const { 
            won, 
            attempts, 
            difficulty, 
            maxAttempts, 
            winStreak 
        } = gameResult;
        
        if (!won) return 0; // Нет очков за поражение
        
        let score = this.basePoints.win;
        
        // Бонус за быстроту
        if (attempts === 1) {
            score += this.basePoints.perfectGame;
        } else if (attempts <= 3) {
            score += this.basePoints.quickWin;
        }
        
        // Бонус за эффективность (процент от максимальных попыток)
        const efficiency = (1 - (attempts / maxAttempts)) * 50;
        score += Math.floor(efficiency);
        
        // Бонус за серию побед
        if (winStreak > 1) {
            score += (winStreak - 1) * this.basePoints.streakBonus;
        }
        
        // Множитель за сложность
        score *= this.difficultyMultipliers[difficulty];
        
        return Math.floor(score);
    }
    
    // Вычисляем очки за достижение
    calculateAchievementScore(achievement) {
        const basePoints = achievement.points || 10;
        const rarity = achievement.rarity || 'common';
        const multiplier = RARITY_CONFIG[rarity].multiplier;
        
        return Math.floor(basePoints * multiplier);
    }
    
    // Форматируем отображение очков
    formatScore(score) {
        if (score >= 1000000) {
            return (score / 1000000).toFixed(1) + 'M';
        } else if (score >= 1000) {
            return (score / 1000).toFixed(1) + 'K';
        }
        return score.toString();
    }
}

⚙️ Реализация системы достижений

Создаём класс для управления достижениями и их проверки:

⚙️ Менеджер достижений
// Менеджер системы достижений
class AchievementManager {
    constructor(scoreSystem) {
        this.scoreSystem = scoreSystem;
        this.unlockedAchievements = new Set();
        this.playerStats = {
            totalGames: 0,
            totalWins: 0,
            winStreak: 0,
            maxWinStreak: 0,
            totalScore: 0,
            lastGameAttempts: 0,
            bestTime: Infinity,
            perfectGames: 0
        };
        this.onAchievementUnlocked = null; // Колбэк
    }
    
    // Обновляем статистику после игры
    updateStats(gameResult) {
        const { won, attempts, timeSpent, difficulty } = gameResult;
        
        this.playerStats.totalGames++;
        this.playerStats.lastGameAttempts = attempts;
        
        if (won) {
            this.playerStats.totalWins++;
            this.playerStats.winStreak++;
            this.playerStats.maxWinStreak = Math.max(
                this.playerStats.maxWinStreak, 
                this.playerStats.winStreak
            );
            
            if (attempts === 1) {
                this.playerStats.perfectGames++;
            }
            
            if (timeSpent < this.playerStats.bestTime) {
                this.playerStats.bestTime = timeSpent;
            }
            
            // Добавляем очки
            const gameScore = this.scoreSystem.calculateGameScore({
                won, attempts, difficulty, 
                maxAttempts: 7, // Предполагаем стандарт
                winStreak: this.playerStats.winStreak
            });
            
            this.playerStats.totalScore += gameScore;
            
        } else {
            this.playerStats.winStreak = 0; // Сброс серии
        }
        
        // Проверяем новые достижения
        this.checkAchievements();
    }
    
    // Проверяем все достижения
    checkAchievements() {
        const newAchievements = [];
        
        // Проходим по всем категориям достижений
        for (const category of Object.values(ACHIEVEMENTS)) {
            for (const achievement of Object.values(category)) {
                // Пропускаем уже разблокированные
                if (this.unlockedAchievements.has(achievement.id)) {
                    continue;
                }
                
                // Проверяем условие
                if (achievement.condition(this.playerStats)) {
                    this.unlockAchievement(achievement);
                    newAchievements.push(achievement);
                }
            }
        }
        
        return newAchievements;
    }
    
    // Разблокируем достижение
    unlockAchievement(achievement) {
        this.unlockedAchievements.add(achievement.id);
        
        // Добавляем очки за достижение
        const points = this.scoreSystem.calculateAchievementScore(achievement);
        this.playerStats.totalScore += points;
        
        // Уведомляем об разблокировке
        if (this.onAchievementUnlocked) {
            this.onAchievementUnlocked(achievement, points);
        }
        
        console.log(`🏆 Достижение разблокировано: ${achievement.name} (+${points} очков)`);
    }
    
    // Получаем прогресс для достижений с прогрессом
    getAchievementProgress(achievementId) {
        const achievement = this.findAchievementById(achievementId);
        if (!achievement || !achievement.progressTracker) {
            return { current: 0, target: 1, percentage: 0 };
        }
        
        return achievement.progressTracker(this.playerStats);
    }
    
    // Получаем статистику игрока
    getPlayerStats() {
        return {
            ...this.playerStats,
            achievementsCount: this.unlockedAchievements.size,
            winRate: this.playerStats.totalGames > 0 
                ? (this.playerStats.totalWins / this.playerStats.totalGames) * 100
                : 0
        };
    }
}

🏆 Твоё задание

Создай систему достижений для игры "Угадай число":

  1. Спроектируй разнообразные достижения по категориям
  2. Реализуй систему редкости и ценности наград
  3. Создай алгоритм подсчёта очков
  4. Добавь класс AchievementManager
  5. Реализуй автоматическую проверку условий
  6. Создай систему уведомлений о разблокировке
  7. Добавь визуальные эффекты для наград
  8. Реализуй сохранение прогресса в localStorage
  9. Протестируй все типы достижений

💡 Помни: хорошие достижения мотивируют и создают долгосрочные цели!

Следующий урок: Геймификация и прогресс (Часть 1) →