/
dayekb
/
vibecoding_clicktocontinue
Обзор
Документация
Войти
/
dayekb
/
vibecoding_clicktocontinue
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
script.js
1 371 строка
54 KB
dayekb
upload files
07 сен 2025, 23:39
07 сен 2025, 23:39
222f4db
Код
Авторство
О чём код?
class ClickToContinueGame { constructor() { this.mainCounter = 1000000; this.clicksPerClick = 1; this.autoClickers = []; this.upgradeWindows = []; this.puzzles = []; this.gameState = { unlockedUpgrades: [], completedPuzzles: [], roomChanges: 0 }; this.initializeGame(); this.setupEventListeners(); this.startAutoClickers(); } initializeGame() { this.mainCounterElement = document.getElementById('mainCounter'); this.mainButton = document.getElementById('mainButton'); this.bunkerDoor = document.getElementById('bunkerDoor'); this.upgradeWindowsContainer = document.getElementById('upgradeWindows'); this.puzzleModal = document.getElementById('puzzleModal'); this.notificationsContainer = document.getElementById('notifications'); this.scatteredUpgrades = document.getElementById('scatteredUpgrades'); this.clickPowerInfo = document.getElementById('clickPowerInfo'); this.autoClickerPowerInfo = document.getElementById('autoClickerPowerInfo'); this.updateMainCounter(); this.initializeUpgrades(); this.initializeStoryElements(); this.startAmbientEffects(); } setupEventListeners() { this.mainButton.addEventListener('click', () => this.handleMainClick()); // Обработчики для модального окна мини-игр document.getElementById('submitAnswer').addEventListener('click', () => this.submitMiniGame()); document.getElementById('skipPuzzle').addEventListener('click', () => this.skipMiniGame()); } handleMainClick() { let clicksToRemove = this.clicksPerClick; // Эффект удачи - шанс на двойные клики if (this.luckModeActive && Math.random() < 0.15) { clicksToRemove *= 2; this.showNotification('Удача! Двойные клики!', 'success'); } // Уменьшаем счетчик this.mainCounter = Math.max(0, this.mainCounter - clicksToRemove); // Уменьшаем счетчики доступных улучшений this.upgrades.forEach(upgrade => { // Проверяем, достигнут ли порог для открытия улучшения const remaining = Math.max(0, upgrade.threshold - this.mainCounter); if (remaining <= 0 && !upgrade.completed && upgrade.counter > 0) { upgrade.counter = Math.max(0, upgrade.counter - clicksToRemove); } }); // Добавляем эффект клика this.mainButton.classList.add('click-effect'); setTimeout(() => this.mainButton.classList.remove('click-effect'), 200); // Обновляем отображение this.updateMainCounter(); // Обновляем панель улучшений this.renderUpgrades(); // Проверяем на победу if (this.mainCounter === 0) { this.handleVictory(); } // Случайные события this.handleRandomEvents(); } updateMainCounter() { this.mainCounterElement.textContent = this.mainCounter.toLocaleString(); this.mainCounterElement.classList.add('counter-change'); setTimeout(() => this.mainCounterElement.classList.remove('counter-change'), 300); // Обновляем отображение силы кликов this.updatePowerDisplay(); } updatePowerDisplay() { const clickPower = this.getClickPower(); const autoClickerPower = this.getAutoClickerPower(); if (this.clickPowerInfo) { this.clickPowerInfo.textContent = `💪 Сила клика: ${clickPower}`; } if (this.autoClickerPowerInfo) { this.autoClickerPowerInfo.textContent = `🤖 Автокликер: ${autoClickerPower}`; } } applyUpgrade(type) { switch (type) { case 'autoclicker': this.addAutoClicker(1, 2000); break; case 'autoclicker2': this.addAutoClicker(2, 1500); break; case 'autoclicker3': this.addAutoClicker(3, 1000); break; case 'autoclicker4': this.addAutoClicker(5, 800); break; case 'autoclicker5': this.addAutoClicker(10, 500); break; case 'multiclick': this.clicksPerClick += 2; this.showNotification('Мульти-клик I! +2 клика за раз: ' + this.clicksPerClick, 'success'); break; case 'multiclick2': this.clicksPerClick += 5; this.showNotification('Мульти-клик II! +5 кликов за раз: ' + this.clicksPerClick, 'success'); break; case 'multiclick3': this.clicksPerClick += 10; this.showNotification('Мульти-клик III! +10 кликов за раз: ' + this.clicksPerClick, 'success'); break; case 'multiclick4': this.clicksPerClick += 25; this.showNotification('Мульти-клик IV! +25 кликов за раз: ' + this.clicksPerClick, 'success'); break; case 'multiclick5': this.clicksPerClick += 50; this.showNotification('Мульти-клик V! +50 кликов за раз: ' + this.clicksPerClick, 'success'); break; case 'speed': this.clicksPerClick += 1; this.showNotification('Скорость увеличена! +1 клик за раз', 'success'); break; case 'bonus': this.activateBonusClicks(); break; case 'chaos': this.activateChaosMode(); break; case 'room': this.changeRoomAppearance(); break; case 'mystery': this.addMysteryObject(); break; case 'power': this.clicksPerClick += 3; this.showNotification('Сила клика увеличена! +3 клика за раз', 'success'); break; case 'luck': this.activateLuckMode(); break; case 'time': this.activateTimeSlowdown(); break; case 'final': this.activateFinalUpgrade(); break; } } addAutoClicker(clicks = 1, interval = 2000) { const autoClicker = { id: Date.now(), interval: interval, clicks: clicks, timer: null }; // Запускаем автокликер autoClicker.timer = setInterval(() => { this.mainCounter = Math.max(0, this.mainCounter - clicks); this.updateMainCounter(); this.renderUpgrades(); }, interval); this.autoClickers.push(autoClicker); this.showNotification(`Автокликер добавлен! ${clicks} кликов каждые ${interval}мс`, 'success'); } activateBonusClicks() { this.bonusClicksActive = true; this.showNotification('Бонусные клики активированы!', 'success'); // Случайные бонусные клики setInterval(() => { if (this.bonusClicksActive && Math.random() < 0.1) { this.mainCounter = Math.max(0, this.mainCounter - 10); this.updateMainCounter(); this.showNotification('Бонус! -10 кликов!', 'success'); } }, 2000); } activateLuckMode() { this.luckModeActive = true; this.showNotification('Режим удачи активирован!', 'success'); } activateTimeSlowdown() { this.timeSlowdownActive = true; this.showNotification('Замедление времени активировано!', 'success'); // Замедляем анимации document.body.style.animationDuration = '2s'; setTimeout(() => { document.body.style.animationDuration = ''; }, 10000); } changeRoomAppearance() { this.gameState.roomChanges++; const room = document.querySelector('.room'); const themes = [ { bg: 'linear-gradient(45deg, #ff6b6b, #ffa500)', color: '#fff' }, { bg: 'linear-gradient(45deg, #4ecdc4, #44a08d)', color: '#fff' }, { bg: 'linear-gradient(45deg, #667eea, #764ba2)', color: '#fff' }, { bg: 'linear-gradient(45deg, #f093fb, #f5576c)', color: '#fff' }, { bg: 'linear-gradient(45deg, #4facfe, #00f2fe)', color: '#fff' } ]; const theme = themes[this.gameState.roomChanges % themes.length]; room.style.background = theme.bg; room.style.color = theme.color; this.showNotification('Комната изменилась!', 'success'); } activateFinalUpgrade() { this.showNotification('Финальное улучшение активировано!', 'success'); this.clicksPerClick *= 10; // Дверь начинает светиться const doorPanel = document.querySelector('.door-panel'); doorPanel.classList.add('unlocked'); } startAutoClickers() { setInterval(() => { this.autoClickers.forEach(clicker => { this.mainCounter = Math.max(0, this.mainCounter - clicker.clicks); }); if (this.autoClickers.length > 0) { this.updateMainCounter(); } }, 1000); } handleRandomEvents() { if (Math.random() < 0.001) { // 0.1% шанс const events = [ () => { this.mainCounter = Math.max(0, this.mainCounter - 100); this.showNotification('Внезапный бонус! -100 кликов!', 'success'); }, () => { this.mainCounter = Math.min(10000000, this.mainCounter + 50); this.showNotification('Неожиданная задержка! +50 кликов!', 'warning'); }, () => { this.clicksPerClick += 1; this.showNotification('Сила клика увеличена!', 'success'); } ]; const randomEvent = events[Math.floor(Math.random() * events.length)]; randomEvent(); this.updateMainCounter(); } } handleVictory() { this.showNotification('ПОБЕДА! Дверь бункера открыта!', 'success'); const doorPanel = document.querySelector('.door-panel'); doorPanel.classList.add('unlocked'); doorPanel.querySelector('.door-text').textContent = 'ОТКРЫТО'; doorPanel.querySelector('.lock-icon').textContent = '🔓'; // Финальная анимация document.body.style.animation = 'victoryPulse 2s infinite'; } showNotification(message, type = 'success') { const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.textContent = message; this.notificationsContainer.appendChild(notification); setTimeout(() => notification.classList.add('show'), 100); setTimeout(() => { notification.classList.remove('show'); setTimeout(() => notification.remove(), 300); }, 3000); } initializeUpgrades() { this.upgrades = [ { id: 'multiclick', threshold: 100, title: 'Мульти-клик I', description: 'Увеличивает количество кликов за раз', unlocked: false, completed: false, counter: 50, level: 1, maxLevel: 5 }, { id: 'autoclicker', threshold: 1000, title: 'Автокликер I', description: 'Автоматически кликает каждые 2 секунды', unlocked: false, completed: false, counter: 100, level: 1, maxLevel: 5 }, { id: 'speed', threshold: 10000, title: 'Ускорение', description: 'Увеличивает скорость кликов', unlocked: false, completed: false, counter: 200 }, { id: 'bonus', threshold: 50000, title: 'Бонусные Клики', description: 'Случайные бонусные клики', unlocked: false, completed: false, counter: 500 }, { id: 'chaos', threshold: 100000, title: 'Режим Хаоса', description: 'Случайные события и эффекты', unlocked: false, completed: false, counter: 1000 }, { id: 'room', threshold: 200000, title: 'Изменение Комнаты', description: 'Меняет внешний вид комнаты', unlocked: false, completed: false, counter: 2000 }, { id: 'mystery', threshold: 300000, title: 'Таинственный Объект', description: 'Странный объект появляется в комнате', unlocked: false, completed: false, counter: 3000 }, { id: 'power', threshold: 400000, title: 'Сила Клика', description: 'Увеличивает силу каждого клика', unlocked: false, completed: false, counter: 4000 }, { id: 'luck', threshold: 500000, title: 'Удача', description: 'Шанс на двойные клики', unlocked: false, completed: false, counter: 5000 }, { id: 'time', threshold: 600000, title: 'Время', description: 'Замедляет время для точности', unlocked: false, completed: false, counter: 6000 }, { id: 'final', threshold: 700000, title: 'Финальное Улучшение', description: 'Последний шаг к свободе', unlocked: false, completed: false, counter: 10000 }, // Дополнительные уровни мульти-клика { id: 'multiclick2', threshold: 50000, title: 'Мульти-клик II', description: 'Еще больше кликов за раз', unlocked: false, completed: false, counter: 200, level: 2, maxLevel: 5 }, { id: 'multiclick3', threshold: 150000, title: 'Мульти-клик III', description: 'Мощные клики', unlocked: false, completed: false, counter: 500, level: 3, maxLevel: 5 }, { id: 'multiclick4', threshold: 300000, title: 'Мульти-клик IV', description: 'Эпические клики', unlocked: false, completed: false, counter: 1000, level: 4, maxLevel: 5 }, { id: 'multiclick5', threshold: 500000, title: 'Мульти-клик V', description: 'Легендарные клики', unlocked: false, completed: false, counter: 2000, level: 5, maxLevel: 5 }, // Дополнительные уровни автокликера { id: 'autoclicker2', threshold: 60000, title: 'Автокликер II', description: 'Быстрее кликает', unlocked: false, completed: false, counter: 300, level: 2, maxLevel: 5 }, { id: 'autoclicker3', threshold: 180000, title: 'Автокликер III', description: 'Очень быстро кликает', unlocked: false, completed: false, counter: 800, level: 3, maxLevel: 5 }, { id: 'autoclicker4', threshold: 350000, title: 'Автокликер IV', description: 'Молниеносно кликает', unlocked: false, completed: false, counter: 1500, level: 4, maxLevel: 5 }, { id: 'autoclicker5', threshold: 550000, title: 'Автокликер V', description: 'Безумно быстро кликает', unlocked: false, completed: false, counter: 3000, level: 5, maxLevel: 5 } ]; this.renderUpgrades(); } renderUpgrades() { // Очищаем только если это первый рендер if (!this.upgradesRendered) { this.scatteredUpgrades.innerHTML = ''; } this.upgrades.forEach((upgrade, index) => { let upgradeElement = document.getElementById(`upgrade-${upgrade.id}`); // Создаем элемент только если его еще нет if (!upgradeElement) { upgradeElement = document.createElement('div'); upgradeElement.className = 'upgrade-item'; upgradeElement.id = `upgrade-${upgrade.id}`; this.scatteredUpgrades.appendChild(upgradeElement); // Позиционируем только при создании this.positionUpgradeElement(upgradeElement, index); } // Для декрементального счетчика: если mainCounter <= threshold, то улучшение доступно // remaining показывает сколько кликов нужно до достижения порога const remaining = Math.max(0, upgrade.threshold - this.mainCounter); let statusIcon = '🔒'; let statusClass = 'locked'; if (upgrade.completed) { statusIcon = '✅'; statusClass = 'completed'; } else if (remaining <= 0) { statusIcon = '🎯'; statusClass = 'available'; } // Уменьшаем счетчик улучшения только если оно доступно и не завершено if (remaining <= 0 && !upgrade.completed && upgrade.counter > 0) { // Счетчик уменьшается только при клике, а не при каждом рендере // Это будет обрабатываться в handleMainClick } upgradeElement.className = `upgrade-item ${statusClass}`; // Определяем текст прогресса let progressText = ''; if (upgrade.completed) { progressText = '✅ Завершено'; } else if (remaining <= 0) { progressText = upgrade.counter > 0 ? `Счетчик: ${upgrade.counter}` : '🎯 Готово к открытию'; } else { progressText = `Осталось: ${remaining.toLocaleString()} кликов`; } upgradeElement.innerHTML = ` <div class="status">${statusIcon}</div> <h4>${upgrade.title}</h4> <div class="description">${upgrade.description}</div> <div class="progress">${progressText}</div> `; upgradeElement.style.opacity = '1'; if (remaining <= 0 && !upgrade.completed && upgrade.counter <= 0) { upgradeElement.addEventListener('click', () => this.startMiniGame(upgrade)); } }); this.upgradesRendered = true; } positionUpgradeElement(element, index) { // Сетка 4x5 с большими промежутками, избегающая область двери const positions = [ // Левая колонка (2% от левого края) { top: '8%', left: '2%' }, { top: '20%', left: '2%' }, { top: '32%', left: '2%' }, { top: '44%', left: '2%' }, { top: '56%', left: '2%' }, // Левая-центральная колонка (25% от левого края) { top: '8%', left: '25%' }, { top: '20%', left: '25%' }, { top: '32%', left: '25%' }, { top: '44%', left: '25%' }, { top: '56%', left: '25%' }, // Правая-центральная колонка (50% от левого края) { top: '8%', left: '50%' }, { top: '20%', left: '50%' }, { top: '32%', left: '50%' }, { top: '44%', left: '50%' }, { top: '56%', left: '50%' }, // Правая колонка (75% от левого края, только верхняя половина) { top: '8%', left: '75%' }, { top: '20%', left: '75%' }, { top: '32%', left: '75%' }, { top: '44%', left: '75%' }, // Дополнительные позиции в левой части для большего количества улучшений { top: '68%', left: '2%' }, { top: '68%', left: '25%' }, { top: '68%', left: '50%' }, { top: '80%', left: '2%' }, { top: '80%', left: '25%' }, { top: '80%', left: '50%' } ]; const position = positions[index % positions.length]; element.style.top = position.top; element.style.left = position.left; element.style.zIndex = 10 + index; } getClickPower() { return this.clicksPerClick; } getAutoClickerPower() { const total = this.autoClickers.reduce((total, clicker) => total + clicker.clicks, 0); console.log('Автокликеры:', this.autoClickers.length, 'Общая сила:', total); return total; } startMiniGame(upgrade) { this.currentUpgrade = upgrade; const gameType = this.getRandomGameType(); this.showMiniGame(gameType); } getRandomGameType() { const games = ['number', 'reaction', 'memory', 'typing', 'math', 'sequence', 'color']; return games[Math.floor(Math.random() * games.length)]; } showMiniGame(gameType) { const modal = this.puzzleModal; const title = document.getElementById('puzzleTitle'); const game = document.getElementById('puzzleGame'); const submitBtn = document.getElementById('submitAnswer'); modal.classList.add('show'); switch (gameType) { case 'number': this.setupNumberGame(title, game, submitBtn); break; case 'reaction': this.setupReactionGame(title, game, submitBtn); break; case 'memory': this.setupMemoryGame(title, game, submitBtn); break; case 'typing': this.setupTypingGame(title, game, submitBtn); break; case 'math': this.setupMathGame(title, game, submitBtn); break; case 'sequence': this.setupSequenceGame(title, game, submitBtn); break; case 'color': this.setupColorGame(title, game, submitBtn); break; } } setupNumberGame(title, game, submitBtn) { // Сбрасываем состояние игры this.gameWon = false; title.textContent = 'Угадай число!'; const targetNumber = Math.floor(Math.random() * 10) + 1; this.gameTarget = targetNumber; game.innerHTML = ` <p>Я загадал число от 1 до 10. Угадай какое!</p> <input type="number" id="numberInput" min="1" max="10" placeholder="Введите число"> <p id="numberHint"></p> `; submitBtn.style.display = 'block'; submitBtn.textContent = 'Угадать'; const input = document.getElementById('numberInput'); input.addEventListener('input', (e) => { const guess = parseInt(e.target.value); const hint = document.getElementById('numberHint'); if (guess === targetNumber) { hint.textContent = '🎉 Правильно!'; hint.style.color = 'green'; this.gameWon = true; } else if (guess > targetNumber) { hint.textContent = 'Меньше!'; hint.style.color = 'red'; } else if (guess < targetNumber) { hint.textContent = 'Больше!'; hint.style.color = 'red'; } }); } setupReactionGame(title, game, submitBtn) { // Сбрасываем состояние игры this.gameWon = false; this.reactionStartTime = null; // Очищаем предыдущий таймер если есть if (this.reactionTimer) { clearTimeout(this.reactionTimer); } title.textContent = 'Тест на реакцию!'; game.innerHTML = ` <p>Нажми кнопку когда она станет ЗЕЛЕНОЙ!</p> <button id="reactionBtn" style="width: 200px; height: 100px; background: red; color: white; font-size: 1.5rem; border: none; border-radius: 10px; cursor: pointer;">ЖДИ...</button> <p id="reactionResult"></p> `; submitBtn.style.display = 'none'; const btn = document.getElementById('reactionBtn'); const result = document.getElementById('reactionResult'); // Случайная задержка от 2 до 5 секунд const delay = Math.random() * 3000 + 2000; this.reactionTimer = setTimeout(() => { btn.style.background = 'green'; btn.textContent = 'НАЖМИ!'; this.reactionStartTime = Date.now(); }, delay); btn.addEventListener('click', () => { if (btn.style.background === 'green') { const reactionTime = Date.now() - this.reactionStartTime; if (reactionTime < 500) { result.textContent = '🎉 Отличная реакция!'; result.style.color = 'green'; this.gameWon = true; // Автоматически закрываем игру через 1 секунду setTimeout(() => { this.handleMiniGameWin(); }, 1000); } else { result.textContent = '😔 Слишком медленно!'; result.style.color = 'red'; } } else { result.textContent = '❌ Слишком рано!'; result.style.color = 'red'; } }); } setupMemoryGame(title, game, submitBtn) { // Сбрасываем состояние игры this.gameWon = false; title.textContent = 'Игра на память!'; const sequence = []; for (let i = 0; i < 4; i++) { sequence.push(Math.floor(Math.random() * 4) + 1); } this.memorySequence = sequence; this.memoryInput = []; game.innerHTML = ` <p>Запомни последовательность чисел:</p> <div id="memoryDisplay" style="font-size: 2rem; font-weight: bold; margin: 20px 0;"></div> <p>Теперь введи числа через запятую:</p> <input type="text" id="memoryInput" placeholder="1,2,3,4"> <p id="memoryResult"></p> `; submitBtn.style.display = 'block'; submitBtn.textContent = 'Проверить'; const display = document.getElementById('memoryDisplay'); let index = 0; const showNext = () => { if (index < sequence.length) { display.textContent = sequence[index]; index++; setTimeout(() => { display.textContent = ''; setTimeout(showNext, 500); }, 1000); } }; showNext(); } setupRiddleGame(title, game, submitBtn) { // Сбрасываем состояние игры this.gameWon = false; const riddles = [ { question: "Что можно увидеть с закрытыми глазами?", answer: "сон" }, { question: "Что всегда идет, но никогда не приходит?", answer: "время" }, { question: "Что принадлежит вам, но другие используют чаще?", answer: "имя" }, { question: "Что можно сломать, не держа в руках?", answer: "сердце" }, { question: "Что становится мокрым, когда сохнет?", answer: "полотенце" } ]; const riddle = riddles[Math.floor(Math.random() * riddles.length)]; this.riddleAnswer = riddle.answer; title.textContent = 'Загадка!'; game.innerHTML = ` <p>${riddle.question}</p> <input type="text" id="riddleInput" placeholder="Ваш ответ..."> <p id="riddleResult"></p> `; submitBtn.style.display = 'block'; submitBtn.textContent = 'Ответить'; } setupTypingGame(title, game, submitBtn) { // Сбрасываем состояние игры this.gameWon = false; const words = ['КОМНАТА', 'КНОПКА', 'ДВЕРЬ', 'КЛИК', 'ИГРА']; const targetWord = words[Math.floor(Math.random() * words.length)]; this.typingTarget = targetWord; title.textContent = 'Печать на скорость!'; game.innerHTML = ` <p>Напечатай слово: <strong>${targetWord}</strong></p> <input type="text" id="typingInput" placeholder="Введите слово..." style="font-size: 1.2rem; padding: 10px; width: 200px;"> <p id="typingResult"></p> `; submitBtn.style.display = 'block'; submitBtn.textContent = 'Проверить'; } setupMathGame(title, game, submitBtn) { // Сбрасываем состояние игры this.gameWon = false; const a = Math.floor(Math.random() * 20) + 1; const b = Math.floor(Math.random() * 20) + 1; const operations = ['+', '-', '*']; const op = operations[Math.floor(Math.random() * operations.length)]; let answer; let question; switch(op) { case '+': answer = a + b; question = `${a} + ${b} = ?`; break; case '-': answer = a - b; question = `${a} - ${b} = ?`; break; case '*': answer = a * b; question = `${a} × ${b} = ?`; break; } this.mathAnswer = answer; title.textContent = 'Математика!'; game.innerHTML = ` <p>Решите пример: <strong>${question}</strong></p> <input type="number" id="mathInput" placeholder="Ответ"> <p id="mathResult"></p> `; submitBtn.style.display = 'block'; submitBtn.textContent = 'Ответить'; } setupSequenceGame(title, game, submitBtn) { // Сбрасываем состояние игры this.gameWon = false; const sequences = [ { pattern: [2, 4, 6, 8], next: 10, hint: "Четные числа" }, { pattern: [1, 4, 9, 16], next: 25, hint: "Квадраты" }, { pattern: [1, 1, 2, 3], next: 5, hint: "Фибоначчи" }, { pattern: [5, 10, 15, 20], next: 25, hint: "Кратные 5" } ]; const seq = sequences[Math.floor(Math.random() * sequences.length)]; this.sequenceAnswer = seq.next; title.textContent = 'Последовательность!'; game.innerHTML = ` <p>Найдите следующее число в последовательности:</p> <p><strong>${seq.pattern.join(', ')}</strong></p> <p><em>Подсказка: ${seq.hint}</em></p> <input type="number" id="sequenceInput" placeholder="Следующее число"> <p id="sequenceResult"></p> `; submitBtn.style.display = 'block'; submitBtn.textContent = 'Ответить'; } setupColorGame(title, game, submitBtn) { // Сбрасываем состояние игры this.gameWon = false; const colors = ['КРАСНЫЙ', 'СИНИЙ', 'ЗЕЛЕНЫЙ', 'ЖЕЛТЫЙ', 'ФИОЛЕТОВЫЙ']; const targetColor = colors[Math.floor(Math.random() * colors.length)]; this.colorTarget = targetColor; title.textContent = 'Цвета!'; game.innerHTML = ` <p>Назовите цвет: <span style="color: ${targetColor.toLowerCase()}; font-size: 2rem; font-weight: bold;">${targetColor}</span></p> <input type="text" id="colorInput" placeholder="Название цвета"> <p id="colorResult"></p> `; submitBtn.style.display = 'block'; submitBtn.textContent = 'Ответить'; } submitMiniGame() { const game = document.getElementById('puzzleGame'); let won = false; // Проверяем тип игры и результат if (game.querySelector('#numberInput')) { const input = document.getElementById('numberInput'); const guess = parseInt(input.value); if (guess === this.gameTarget) { won = true; } } else if (game.querySelector('#memoryInput')) { const input = document.getElementById('memoryInput'); const userSequence = input.value.split(',').map(n => parseInt(n.trim())); if (JSON.stringify(userSequence) === JSON.stringify(this.memorySequence)) { won = true; } } else if (game.querySelector('#riddleInput')) { const input = document.getElementById('riddleInput'); const answer = input.value.toLowerCase().trim(); if (answer === this.riddleAnswer) { won = true; } } else if (game.querySelector('#typingInput')) { const input = document.getElementById('typingInput'); const typed = input.value.toUpperCase().trim(); if (typed === this.typingTarget) { won = true; } } else if (game.querySelector('#mathInput')) { const input = document.getElementById('mathInput'); const answer = parseInt(input.value); if (answer === this.mathAnswer) { won = true; } } else if (game.querySelector('#sequenceInput')) { const input = document.getElementById('sequenceInput'); const answer = parseInt(input.value); if (answer === this.sequenceAnswer) { won = true; } } else if (game.querySelector('#colorInput')) { const input = document.getElementById('colorInput'); const answer = input.value.toUpperCase().trim(); if (answer === this.colorTarget) { won = true; } } if (won) { this.handleMiniGameWin(); } else { this.showNotification('Попробуйте еще раз!', 'error'); } } skipMiniGame() { this.puzzleModal.classList.remove('show'); this.showNotification('Мини-игра пропущена. Попробуйте позже.', 'warning'); } handleMiniGameWin() { this.puzzleModal.classList.remove('show'); if (this.currentUpgrade) { this.currentUpgrade.completed = true; this.applyUpgrade(this.currentUpgrade.id); this.renderUpgrades(); this.showNotification('Мини-игра пройдена! Улучшение активировано!', 'success'); } } initializeStoryElements() { this.storyMessages = [ "Вы просыпаетесь в белой комнате...", "Единственный способ взаимодействия - эта кнопка...", "Что-то не так с этой комнатой...", "Стены кажутся живыми...", "Вы слышите странные звуки...", "Время здесь течет по-другому...", "Кто-то наблюдает за вами...", "Реальность начинает трескаться...", "Вы приближаетесь к истине...", "Дверь ждет вас..." ]; this.currentStoryIndex = 0; this.storyThresholds = [999900, 999000, 990000, 950000, 900000, 800000, 700000, 600000, 500000, 400000, 300000, 200000, 100000, 50000, 10000, 1000, 0]; } startAmbientEffects() { // Случайные звуковые эффекты (визуальные) setInterval(() => { if (Math.random() < 0.05) { this.createAmbientEffect(); } }, 3000); // Периодические сообщения истории setInterval(() => { this.checkStoryProgress(); }, 2000); } createAmbientEffect() { const effects = [ () => this.createFloatingText("..."), () => this.createFloatingText("?"), () => this.createFloatingText("!"), () => this.createGlitchEffect(), () => this.createShadowEffect() ]; const randomEffect = effects[Math.floor(Math.random() * effects.length)]; randomEffect(); } createFloatingText(text) { const floatingText = document.createElement('div'); floatingText.textContent = text; floatingText.style.cssText = ` position: absolute; font-size: 2rem; color: rgba(0,0,0,0.3); pointer-events: none; z-index: 5; animation: floatUp 3s ease-out forwards; `; const x = Math.random() * window.innerWidth; const y = Math.random() * window.innerHeight; floatingText.style.left = `${x}px`; floatingText.style.top = `${y}px`; document.querySelector('.room').appendChild(floatingText); setTimeout(() => floatingText.remove(), 3000); } createGlitchEffect() { const room = document.querySelector('.room'); room.style.filter = 'hue-rotate(90deg) contrast(1.5)'; room.style.transform = 'scale(1.02)'; setTimeout(() => { room.style.filter = ''; room.style.transform = ''; }, 200); } createShadowEffect() { const shadow = document.createElement('div'); shadow.style.cssText = ` position: absolute; width: 100px; height: 100px; background: radial-gradient(circle, rgba(0,0,0,0.1) 0%, transparent 70%); border-radius: 50%; pointer-events: none; z-index: 1; animation: shadowMove 4s ease-in-out infinite; `; const x = Math.random() * (window.innerWidth - 100); const y = Math.random() * (window.innerHeight - 100); shadow.style.left = `${x}px`; shadow.style.top = `${y}px`; document.querySelector('.room').appendChild(shadow); setTimeout(() => shadow.remove(), 4000); } checkStoryProgress() { if (this.currentStoryIndex < this.storyThresholds.length) { const threshold = this.storyThresholds[this.currentStoryIndex]; if (this.mainCounter <= threshold) { this.showStoryMessage(this.storyMessages[this.currentStoryIndex]); this.currentStoryIndex++; } } } showStoryMessage(message) { const storyNotification = document.createElement('div'); storyNotification.className = 'story-message'; storyNotification.textContent = message; storyNotification.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(0,0,0,0.8); color: white; padding: 20px 40px; border-radius: 10px; font-size: 1.2rem; z-index: 1000; text-align: center; animation: storyFade 4s ease-in-out forwards; `; document.body.appendChild(storyNotification); setTimeout(() => storyNotification.remove(), 4000); } addMysteryObject() { const mysteryObjects = ['🔮', '👁️', '🌀', '⚡', '🌙', '🔺', '💎', '🎭']; const mysteryObject = document.createElement('div'); mysteryObject.className = 'mystery-object'; mysteryObject.innerHTML = mysteryObjects[Math.floor(Math.random() * mysteryObjects.length)]; mysteryObject.style.cssText = ` position: absolute; font-size: 3rem; animation: float 3s ease-in-out infinite; cursor: pointer; z-index: 15; transition: all 0.3s ease; `; const x = Math.random() * (window.innerWidth - 100); const y = Math.random() * (window.innerHeight - 100); mysteryObject.style.left = `${x}px`; mysteryObject.style.top = `${y}px`; mysteryObject.addEventListener('click', () => { this.mainCounter = Math.max(0, this.mainCounter - 1000); this.updateMainCounter(); mysteryObject.style.transform = 'scale(0) rotate(360deg)'; setTimeout(() => mysteryObject.remove(), 300); this.showNotification('Таинственный объект исчез! -1000 кликов!', 'success'); }); mysteryObject.addEventListener('mouseenter', () => { mysteryObject.style.transform = 'scale(1.2)'; }); mysteryObject.addEventListener('mouseleave', () => { mysteryObject.style.transform = 'scale(1)'; }); document.querySelector('.room').appendChild(mysteryObject); this.showNotification('Таинственный объект появился!', 'success'); } activateChaosMode() { this.showNotification('Режим хаоса активирован!', 'warning'); this.chaosActive = true; // Добавляем случайные эффекты this.chaosInterval = setInterval(() => { if (Math.random() < 0.15) { this.handleRandomChaosEvent(); } }, 3000); // Изменяем кнопку this.mainButton.style.background = 'linear-gradient(45deg, #ff6b6b, #ffa500)'; this.mainButton.style.animation = 'chaosPulse 1s infinite'; } handleRandomChaosEvent() { const chaosEvents = [ () => { this.mainButton.style.transform = 'rotate(180deg) scale(1.2)'; setTimeout(() => { this.mainButton.style.transform = 'rotate(0deg) scale(1)'; }, 2000); this.showNotification('Кнопка перевернулась и увеличилась!', 'warning'); }, () => { this.mainButton.style.background = 'linear-gradient(45deg, #ff0000, #ff6600)'; this.mainButton.style.boxShadow = '0 0 30px #ff0000'; setTimeout(() => { this.mainButton.style.background = ''; this.mainButton.style.boxShadow = ''; }, 3000); this.showNotification('Кнопка покраснела и светится!', 'warning'); }, () => { document.body.style.filter = 'hue-rotate(180deg) saturate(2)'; setTimeout(() => document.body.style.filter = '', 2000); this.showNotification('Цвета инвертировались!', 'warning'); }, () => { this.mainButton.style.borderRadius = '50%'; setTimeout(() => this.mainButton.style.borderRadius = '', 2000); this.showNotification('Кнопка стала круглой!', 'warning'); }, () => { this.mainCounter = Math.max(0, this.mainCounter - 500); this.updateMainCounter(); this.showNotification('Хаос дал вам бонус! -500 кликов!', 'success'); } ]; const randomChaos = chaosEvents[Math.floor(Math.random() * chaosEvents.length)]; randomChaos(); } handleVictory() { this.showNotification('ПОБЕДА! Дверь бункера открыта!', 'success'); const doorPanel = document.querySelector('.door-panel'); doorPanel.classList.add('unlocked'); doorPanel.querySelector('.door-text').textContent = 'ОТКРЫТО'; doorPanel.querySelector('.lock-icon').textContent = '🔓'; // Добавляем обработчик клика на дверь this.bunkerDoor.addEventListener('click', () => this.handleDoorClick()); // Финальная анимация document.body.style.animation = 'victoryPulse 2s infinite'; // Показываем финальное сообщение setTimeout(() => { this.showStoryMessage("Вы наконец свободны... Но что ждет вас за дверью?"); }, 2000); // Останавливаем хаос если активен if (this.chaosActive && this.chaosInterval) { clearInterval(this.chaosInterval); this.mainButton.style.background = ''; this.mainButton.style.animation = ''; } } handleDoorClick() { if (this.bunkerDoor.querySelector('.door-panel').classList.contains('unlocked')) { this.showNotification('🚪 Дверь открывается...', 'success'); // Финальная анимация двери this.bunkerDoor.style.transform = 'translateX(100px)'; this.bunkerDoor.style.opacity = '0.5'; // Показываем финальное сообщение setTimeout(() => { this.showStoryMessage("🎉 ПОЗДРАВЛЯЕМ! Вы сбежали из белой комнаты!"); this.showStoryMessage("Игра завершена. Спасибо за игру!"); }, 1000); // Останавливаем все автокликеры this.autoClickers.forEach(clicker => { if (clicker.timer) { clearInterval(clicker.timer); } }); // Деактивируем кнопку this.mainButton.style.opacity = '0.5'; this.mainButton.style.pointerEvents = 'none'; } else { this.showNotification('🔒 Дверь заблокирована. Продолжайте кликать!', 'warning'); } } } // Добавляем CSS для анимаций const style = document.createElement('style'); style.textContent = ` @keyframes float { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-20px); } } @keyframes victoryPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.02); } } @keyframes floatUp { 0% { opacity: 0; transform: translateY(20px) scale(0.8); } 50% { opacity: 1; transform: translateY(-10px) scale(1.1); } 100% { opacity: 0; transform: translateY(-40px) scale(0.9); } } @keyframes shadowMove { 0%, 100% { transform: translateX(0px) translateY(0px); } 25% { transform: translateX(20px) translateY(-10px); } 50% { transform: translateX(-10px) translateY(20px); } 75% { transform: translateX(-20px) translateY(-5px); } } @keyframes storyFade { 0% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); } 20%, 80% { opacity: 1; transform: translate(-50%, -50%) scale(1); } 100% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); } } @keyframes chaosPulse { 0%, 100% { transform: scale(1); box-shadow: 0 8px 20px rgba(255, 107, 107, 0.3); } 50% { transform: scale(1.05); box-shadow: 0 12px 30px rgba(255, 107, 107, 0.6); } } .story-message { font-family: 'Courier New', monospace; text-shadow: 2px 2px 4px rgba(0,0,0,0.5); } `; document.head.appendChild(style); // Запускаем игру const game = new ClickToContinueGame();