Spaces:
Running
Running
| <html lang="ru"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Кликер - Игра на реакцию</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .target { | |
| transition: all 0.3s ease; | |
| box-shadow: 0 0 15px rgba(255, 0, 0, 0.5); | |
| animation: pulse 1.5s infinite alternate; | |
| } | |
| @keyframes pulse { | |
| from { transform: scale(1); } | |
| to { transform: scale(1.1); } | |
| } | |
| .explosion { | |
| position: absolute; | |
| width: 60px; | |
| height: 60px; | |
| background: radial-gradient(circle, rgba(255,255,0,0.8) 0%, rgba(255,100,0,0.8) 50%, rgba(255,0,0,0) 70%); | |
| border-radius: 50%; | |
| pointer-events: none; | |
| animation: explode 0.5s forwards; | |
| } | |
| @keyframes explode { | |
| 0% { transform: scale(0); opacity: 1; } | |
| 100% { transform: scale(2); opacity: 0; } | |
| } | |
| .progress-bar { | |
| transition: width 0.3s ease; | |
| } | |
| .combo { | |
| animation: comboPop 0.5s; | |
| } | |
| @keyframes comboPop { | |
| 0% { transform: scale(1); } | |
| 50% { transform: scale(1.5); } | |
| 100% { transform: scale(1); } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-900 text-white min-h-screen flex flex-col"> | |
| <!-- Шапка --> | |
| <header class="bg-gray-800 py-4 px-6 shadow-lg"> | |
| <div class="container mx-auto flex justify-between items-center"> | |
| <h1 class="text-2xl font-bold text-yellow-400 flex items-center"> | |
| <i class="fas fa-bullseye mr-2"></i> Кликер | |
| </h1> | |
| <div class="flex items-center space-x-4"> | |
| <div class="bg-gray-700 px-4 py-2 rounded-lg flex items-center"> | |
| <i class="fas fa-star text-yellow-400 mr-2"></i> | |
| <span id="score" class="font-bold">0</span> | |
| </div> | |
| <div class="bg-gray-700 px-4 py-2 rounded-lg flex items-center"> | |
| <i class="fas fa-bolt text-blue-400 mr-2"></i> | |
| <span id="combo" class="font-bold">0x</span> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Основное содержимое --> | |
| <main class="flex-grow flex flex-col items-center justify-center relative overflow-hidden p-4"> | |
| <!-- Игровое поле --> | |
| <div id="game-area" class="w-full h-96 md:h-[500px] bg-gray-800 rounded-xl border-2 border-gray-700 relative overflow-hidden"> | |
| <!-- Мишень будет появляться здесь --> | |
| </div> | |
| <!-- Всплывающее сообщение о комбо --> | |
| <div id="combo-message" class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-4xl font-bold text-yellow-400 opacity-0 pointer-events-none"> | |
| COMBO! | |
| </div> | |
| <!-- Прогресс бар уровня --> | |
| <div class="w-full max-w-md mt-6 bg-gray-700 rounded-full h-4"> | |
| <div id="level-progress" class="progress-bar h-full bg-gradient-to-r from-blue-500 to-purple-500 rounded-full" style="width: 0%"></div> | |
| </div> | |
| <div class="mt-2 text-sm text-gray-400"> | |
| Уровень: <span id="level" class="font-bold text-white">1</span> | |
| </div> | |
| </main> | |
| <!-- Панель управления --> | |
| <div class="bg-gray-800 py-4 px-6 shadow-lg"> | |
| <div class="container mx-auto flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0"> | |
| <div class="flex items-center space-x-4"> | |
| <div class="bg-gray-700 px-4 py-2 rounded-lg"> | |
| <div class="text-sm text-gray-400">Рекорд</div> | |
| <div id="highscore" class="font-bold text-yellow-400">0</div> | |
| </div> | |
| <div class="bg-gray-700 px-4 py-2 rounded-lg"> | |
| <div class="text-sm text-gray-400">Время</div> | |
| <div id="time" class="font-bold">60</div> | |
| </div> | |
| </div> | |
| <div class="flex space-x-3"> | |
| <button id="start-btn" class="bg-green-600 hover:bg-green-700 text-white font-bold py-3 px-6 rounded-lg flex items-center transition transform hover:scale-105"> | |
| <i class="fas fa-play mr-2"></i> Старт | |
| </button> | |
| <button id="reset-btn" class="bg-red-600 hover:bg-red-700 text-white font-bold py-3 px-6 rounded-lg flex items-center transition transform hover:scale-105"> | |
| <i class="fas fa-redo mr-2"></i> Сброс | |
| </button> | |
| </div> | |
| <div class="bg-gray-700 px-4 py-2 rounded-lg"> | |
| <div class="text-sm text-gray-400">Сложность</div> | |
| <select id="difficulty" class="bg-gray-800 text-white rounded px-2 py-1"> | |
| <option value="easy">Легко</option> | |
| <option value="medium" selected>Средне</option> | |
| <option value="hard">Сложно</option> | |
| </select> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Модальное окно с результатами --> | |
| <div id="result-modal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center hidden z-50"> | |
| <div class="bg-gray-800 rounded-xl p-8 max-w-md w-full mx-4 border-2 border-yellow-400 transform transition-all duration-300 scale-95 opacity-0"> | |
| <h2 class="text-2xl font-bold text-center text-yellow-400 mb-6">Результаты игры</h2> | |
| <div class="space-y-4 mb-6"> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-400">Набрано очков:</span> | |
| <span id="final-score" class="font-bold text-xl">0</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-400">Максимальное комбо:</span> | |
| <span id="final-combo" class="font-bold text-xl">0x</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-400">Попаданий:</span> | |
| <span id="final-hits" class="font-bold text-xl">0</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-400">Точность:</span> | |
| <span id="final-accuracy" class="font-bold text-xl">0%</span> | |
| </div> | |
| </div> | |
| <div class="flex justify-center"> | |
| <button id="close-modal" class="bg-yellow-500 hover:bg-yellow-600 text-gray-900 font-bold py-3 px-6 rounded-lg transition transform hover:scale-105"> | |
| <i class="fas fa-check mr-2"></i> Понятно | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Элементы DOM | |
| const gameArea = document.getElementById('game-area'); | |
| const startBtn = document.getElementById('start-btn'); | |
| const resetBtn = document.getElementById('reset-btn'); | |
| const scoreDisplay = document.getElementById('score'); | |
| const comboDisplay = document.getElementById('combo'); | |
| const highscoreDisplay = document.getElementById('highscore'); | |
| const timeDisplay = document.getElementById('time'); | |
| const levelDisplay = document.getElementById('level'); | |
| const levelProgress = document.getElementById('level-progress'); | |
| const comboMessage = document.getElementById('combo-message'); | |
| const difficultySelect = document.getElementById('difficulty'); | |
| const resultModal = document.getElementById('result-modal'); | |
| const finalScore = document.getElementById('final-score'); | |
| const finalCombo = document.getElementById('final-combo'); | |
| const finalHits = document.getElementById('final-hits'); | |
| const finalAccuracy = document.getElementById('final-accuracy'); | |
| const closeModal = document.getElementById('close-modal'); | |
| // Игровые переменные | |
| let score = 0; | |
| let highscore = localStorage.getItem('highscore') || 0; | |
| let combo = 0; | |
| let hits = 0; | |
| let misses = 0; | |
| let timeLeft = 60; | |
| let gameActive = false; | |
| let timer; | |
| let targetInterval; | |
| let level = 1; | |
| let levelPoints = 0; | |
| let targetSpeed = 1.5; | |
| let targetSize = 60; | |
| let targetLifetime = 2000; | |
| // Обновляем рекорд при загрузке | |
| highscoreDisplay.textContent = highscore; | |
| // Начало игры | |
| startBtn.addEventListener('click', () => { | |
| if (gameActive) return; | |
| // Сброс переменных | |
| score = 0; | |
| combo = 0; | |
| hits = 0; | |
| misses = 0; | |
| timeLeft = 60; | |
| level = 1; | |
| levelPoints = 0; | |
| // Обновление интерфейса | |
| scoreDisplay.textContent = score; | |
| comboDisplay.textContent = combo + 'x'; | |
| timeDisplay.textContent = timeLeft; | |
| levelDisplay.textContent = level; | |
| levelProgress.style.width = '0%'; | |
| // Установка сложности | |
| setDifficulty(); | |
| // Активация игры | |
| gameActive = true; | |
| startBtn.disabled = true; | |
| startBtn.classList.remove('bg-green-600', 'hover:bg-green-700'); | |
| startBtn.classList.add('bg-gray-600', 'cursor-not-allowed'); | |
| // Запуск таймеров | |
| timer = setInterval(updateTimer, 1000); | |
| spawnTarget(); | |
| }); | |
| // Сброс игры | |
| resetBtn.addEventListener('click', () => { | |
| clearInterval(timer); | |
| clearInterval(targetInterval); | |
| gameActive = false; | |
| timeLeft = 60; | |
| timeDisplay.textContent = timeLeft; | |
| startBtn.disabled = false; | |
| startBtn.classList.remove('bg-gray-600', 'cursor-not-allowed'); | |
| startBtn.classList.add('bg-green-600', 'hover:bg-green-700'); | |
| // Очистка игрового поля | |
| gameArea.innerHTML = ''; | |
| }); | |
| // Установка сложности | |
| function setDifficulty() { | |
| const difficulty = difficultySelect.value; | |
| switch(difficulty) { | |
| case 'easy': | |
| targetSpeed = 1; | |
| targetSize = 70; | |
| targetLifetime = 2500; | |
| break; | |
| case 'hard': | |
| targetSpeed = 2.5; | |
| targetSize = 50; | |
| targetLifetime = 1500; | |
| break; | |
| default: // medium | |
| targetSpeed = 1.5; | |
| targetSize = 60; | |
| targetLifetime = 2000; | |
| } | |
| } | |
| // Обновление таймера | |
| function updateTimer() { | |
| timeLeft--; | |
| timeDisplay.textContent = timeLeft; | |
| if (timeLeft <= 0) { | |
| endGame(); | |
| } | |
| } | |
| // Создание мишени | |
| function spawnTarget() { | |
| if (!gameActive) return; | |
| // Очищаем предыдущие мишени | |
| gameArea.innerHTML = ''; | |
| // Создаем новую мишень | |
| const target = document.createElement('div'); | |
| target.className = 'target absolute rounded-full bg-red-600 cursor-pointer flex items-center justify-center'; | |
| target.style.width = `${targetSize}px`; | |
| target.style.height = `${targetSize}px`; | |
| // Добавляем внутренний круг для лучшего визуального эффекта | |
| const innerCircle = document.createElement('div'); | |
| innerCircle.className = 'w-3/4 h-3/4 rounded-full bg-white opacity-30'; | |
| target.appendChild(innerCircle); | |
| // Случайная позиция | |
| const maxX = gameArea.clientWidth - targetSize; | |
| const maxY = gameArea.clientHeight - targetSize; | |
| let posX = Math.random() * maxX; | |
| let posY = Math.random() * maxY; | |
| // Направление движения | |
| let dirX = Math.random() > 0.5 ? 1 : -1; | |
| let dirY = Math.random() > 0.5 ? 1 : -1; | |
| target.style.left = `${posX}px`; | |
| target.style.top = `${posY}px`; | |
| // Добавляем мишень на поле | |
| gameArea.appendChild(target); | |
| // Обработчик клика | |
| target.addEventListener('click', () => { | |
| if (!gameActive) return; | |
| // Увеличиваем счет | |
| hits++; | |
| const points = 10 + Math.floor(combo / 3); | |
| score += points; | |
| scoreDisplay.textContent = score; | |
| // Увеличиваем комбо | |
| combo++; | |
| comboDisplay.textContent = combo + 'x'; | |
| // Анимация комбо | |
| if (combo % 5 === 0) { | |
| showComboMessage(); | |
| comboDisplay.classList.add('combo'); | |
| setTimeout(() => comboDisplay.classList.remove('combo'), 500); | |
| } | |
| // Прогресс уровня | |
| levelPoints += points; | |
| updateLevelProgress(); | |
| // Эффект взрыва | |
| createExplosion(posX + targetSize/2, posY + targetSize/2); | |
| // Удаляем мишень | |
| target.remove(); | |
| // Создаем новую мишень с небольшой задержкой | |
| setTimeout(spawnTarget, 300); | |
| }); | |
| // Движение мишени | |
| let moveInterval = setInterval(() => { | |
| if (!gameActive) { | |
| clearInterval(moveInterval); | |
| return; | |
| } | |
| posX += dirX * targetSpeed; | |
| posY += dirY * targetSpeed; | |
| // Отскок от границ | |
| if (posX <= 0 || posX >= maxX) { | |
| dirX *= -1; | |
| } | |
| if (posY <= 0 || posY >= maxY) { | |
| dirY *= -1; | |
| } | |
| target.style.left = `${posX}px`; | |
| target.style.top = `${posY}px`; | |
| }, 16); | |
| // Автоматическое исчезновение мишени | |
| setTimeout(() => { | |
| if (target.parentNode === gameArea) { | |
| misses++; | |
| combo = 0; | |
| comboDisplay.textContent = combo + 'x'; | |
| target.remove(); | |
| spawnTarget(); | |
| } | |
| clearInterval(moveInterval); | |
| }, targetLifetime); | |
| } | |
| // Создание эффекта взрыва | |
| function createExplosion(x, y) { | |
| const explosion = document.createElement('div'); | |
| explosion.className = 'explosion'; | |
| explosion.style.left = `${x - 30}px`; | |
| explosion.style.top = `${y - 30}px`; | |
| gameArea.appendChild(explosion); | |
| setTimeout(() => { | |
| explosion.remove(); | |
| }, 500); | |
| } | |
| // Показ сообщения о комбо | |
| function showComboMessage() { | |
| comboMessage.style.opacity = '1'; | |
| comboMessage.style.transform = 'translate(-50%, -50%) scale(1.5)'; | |
| setTimeout(() => { | |
| comboMessage.style.opacity = '0'; | |
| comboMessage.style.transform = 'translate(-50%, -50%) scale(1)'; | |
| }, 800); | |
| } | |
| // Обновление прогресса уровня | |
| function updateLevelProgress() { | |
| const pointsNeeded = level * 100; | |
| const progress = Math.min((levelPoints / pointsNeeded) * 100, 100); | |
| levelProgress.style.width = `${progress}%`; | |
| if (levelPoints >= pointsNeeded) { | |
| levelUp(); | |
| } | |
| } | |
| // Повышение уровня | |
| function levelUp() { | |
| level++; | |
| levelPoints = 0; | |
| levelDisplay.textContent = level; | |
| // Увеличиваем сложность с уровнем | |
| targetSpeed = Math.min(targetSpeed + 0.1, 3); | |
| targetLifetime = Math.max(targetLifetime - 100, 800); | |
| // Анимация | |
| levelDisplay.classList.add('combo'); | |
| setTimeout(() => levelDisplay.classList.remove('combo'), 500); | |
| } | |
| // Завершение игры | |
| function endGame() { | |
| clearInterval(timer); | |
| clearInterval(targetInterval); | |
| gameActive = false; | |
| startBtn.disabled = false; | |
| startBtn.classList.remove('bg-gray-600', 'cursor-not-allowed'); | |
| startBtn.classList.add('bg-green-600', 'hover:bg-green-700'); | |
| // Очистка игрового поля | |
| gameArea.innerHTML = ''; | |
| // Обновление рекорда | |
| if (score > highscore) { | |
| highscore = score; | |
| highscoreDisplay.textContent = highscore; | |
| localStorage.setItem('highscore', highscore); | |
| } | |
| // Показ результатов | |
| showResults(); | |
| } | |
| // Показ результатов | |
| function showResults() { | |
| finalScore.textContent = score; | |
| finalCombo.textContent = combo + 'x'; | |
| finalHits.textContent = hits; | |
| const totalShots = hits + misses; | |
| const accuracy = totalShots > 0 ? Math.round((hits / totalShots) * 100) : 0; | |
| finalAccuracy.textContent = accuracy + '%'; | |
| // Анимация появления модального окна | |
| resultModal.classList.remove('hidden'); | |
| setTimeout(() => { | |
| const modalContent = resultModal.querySelector('div'); | |
| modalContent.style.opacity = '1'; | |
| modalContent.style.transform = 'scale(1)'; | |
| }, 10); | |
| } | |
| // Закрытие модального окна | |
| closeModal.addEventListener('click', () => { | |
| const modalContent = resultModal.querySelector('div'); | |
| modalContent.style.opacity = '0'; | |
| modalContent.style.transform = 'scale(0.95)'; | |
| setTimeout(() => { | |
| resultModal.classList.add('hidden'); | |
| }, 300); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=artemkutas6/clicker" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |