clicker / index.html
artemkutas6's picture
Игра - Initial Deployment
44b41b3 verified
<!DOCTYPE html>
<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>