race / index.html
DIMASIK5252's picture
Add 2 files
b6e7c3e verified
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Гонки Шерегеш - Лыжные Гонки</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Montserrat', sans-serif;
}
body {
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
color: white;
min-height: 100vh;
overflow-x: hidden;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
position: relative;
}
header {
text-align: center;
margin-bottom: 30px;
position: relative;
z-index: 10;
}
h1 {
font-size: 3rem;
margin-bottom: 10px;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
background: linear-gradient(to right, #fff, #65c7f7);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.subtitle {
font-size: 1.2rem;
opacity: 0.9;
}
.game-area {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.menu {
background: rgba(0, 0, 0, 0.5);
border-radius: 15px;
padding: 30px;
width: 100%;
max-width: 800px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
.menu-title {
font-size: 1.8rem;
margin-bottom: 20px;
text-align: center;
color: #65c7f7;
}
.difficulty-list {
list-style: none;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.difficulty-item {
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
padding: 15px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
border: 1px solid transparent;
}
.difficulty-item:hover {
transform: translateY(-5px);
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.3);
}
.difficulty-item.locked {
opacity: 0.6;
cursor: not-allowed;
position: relative;
overflow: hidden;
}
.difficulty-item.locked::after {
content: '🔒';
position: absolute;
top: 10px;
right: 10px;
font-size: 0.8rem;
}
.difficulty-name {
font-size: 1.3rem;
margin-bottom: 5px;
}
.difficulty-desc {
font-size: 0.9rem;
opacity: 0.8;
margin-bottom: 10px;
}
.difficulty-icon {
font-size: 2rem;
margin-bottom: 10px;
}
.race-canvas {
background: linear-gradient(to bottom, #87CEEB, #E0F7FA);
border-radius: 10px;
display: none;
overflow: hidden;
position: relative;
border: 3px solid rgba(255, 255, 255, 0.3);
}
.game-info {
display: flex;
justify-content: space-between;
width: 100%;
padding: 10px 20px;
background: rgba(0, 0, 0, 0.5);
border-radius: 8px;
margin-bottom: 10px;
}
.score-display {
font-size: 1.2rem;
}
.controls {
margin-top: 20px;
display: flex;
flex-direction: column;
gap: 10px;
}
.btn {
background: linear-gradient(45deg, #65c7f7, #0052d9);
border: none;
color: white;
padding: 12px 25px;
border-radius: 30px;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s ease;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 1px;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(101, 199, 247, 0.4);
}
.btn:active {
transform: translateY(1px);
}
.btn.secondary {
background: rgba(255, 255, 255, 0.1);
}
.btn.secondary:hover {
background: rgba(255, 255, 255, 0.2);
}
.game-over {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.8);
padding: 30px;
border-radius: 15px;
text-align: center;
z-index: 100;
display: none;
width: 80%;
max-width: 500px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.game-over h2 {
font-size: 2rem;
margin-bottom: 20px;
color: #65c7f7;
}
.game-over p {
font-size: 1.2rem;
margin-bottom: 20px;
}
.particles {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 1;
}
.snow {
position: absolute;
width: 3px;
height: 3px;
background: white;
border-radius: 50%;
opacity: 0.7;
animation: fall linear infinite;
}
@keyframes fall {
to {
transform: translateY(100vh) translateX(10vw);
}
}
.mountains {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100px;
background: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.3));
z-index: 2;
}
.mountain {
position: absolute;
bottom: 0;
width: 0;
height: 0;
border-left: 100px solid transparent;
border-right: 100px solid transparent;
border-bottom: 150px solid rgba(255, 255, 255, 0.1);
}
.mountain:nth-child(1) {
left: 10%;
border-bottom-width: 180px;
}
.mountain:nth-child(2) {
left: 30%;
border-bottom-width: 200px;
}
.mountain:nth-child(3) {
left: 60%;
border-bottom-width: 160px;
}
.mountain:nth-child(4) {
left: 80%;
border-bottom-width: 190px;
}
.progress-container {
width: 100%;
height: 20px;
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
margin-bottom: 20px;
overflow: hidden;
}
.progress-bar {
height: 100%;
background: linear-gradient(to right, #65c7f7, #0052d9);
border-radius: 10px;
width: 0%;
transition: width 0.3s ease;
}
</style>
</head>
<body>
<div class="particles" id="particles"></div>
<div class="mountains">
<div class="mountain"></div>
<div class="mountain"></div>
<div class="mountain"></div>
<div class="mountain"></div>
</div>
<div class="container">
<header>
<h1>Гонки Шерегеш</h1>
<p class="subtitle">Испытай свою скорость на заснеженных склонах!</p>
</header>
<div class="game-area">
<div class="menu" id="mainMenu">
<h2 class="menu-title">Выберите испытание</h2>
<ul class="difficulty-list">
<li class="difficulty-item" data-difficulty="easy">
<div class="difficulty-icon">⛷️</div>
<h3 class="difficulty-name">Легкая трасса</h3>
<p class="difficulty-desc">Плавные спуски, идеально для начинающих</p>
<button class="btn">Начать</button>
</li>
<li class="difficulty-item" data-difficulty="medium">
<div class="difficulty-icon">⛷️⛷️</div>
<h3 class="difficulty-name">Средняя трасса</h3>
<p class="difficulty-desc">Больше поворотов и небольшие препятствия</p>
<button class="btn">Начать</button>
</li>
<li class="difficulty-item" data-difficulty="hard" id="hardLevel">
<div class="difficulty-icon">⛷️⛷️⛷️</div>
<h3 class="difficulty-name">Сложная трасса</h3>
<p class="difficulty-desc">Крутые склоны и сложные повороты</p>
<button class="btn">Начать</button>
</li>
<li class="difficulty-item locked" data-difficulty="extreme" id="extremeLevel">
<div class="difficulty-icon">💀</div>
<h3 class="difficulty-name">Экстрим</h3>
<p class="difficulty-desc">Бегите от бурана и выживайте!</p>
<button class="btn">Заблокировано</button>
</li>
<li class="difficulty-item locked" data-difficulty="race" id="raceMode">
<div class="difficulty-icon">🏁</div>
<h3 class="difficulty-name">Режим гонки</h3>
<p class="difficulty-desc">Случайная трасса с выбором сложности</p>
<button class="btn">Заблокировано</button>
</li>
</ul>
</div>
<div class="game-info" style="display: none;" id="gameInfo">
<div class="score-display">
Скорость: <span id="speedDisplay">0</span> км/ч
</div>
<div class="score-display">
Пройдено: <span id="distanceDisplay">0</span> м
</div>
<div class="score-display">
Время: <span id="timeDisplay">0</span> сек
</div>
</div>
<div class="progress-container" id="progressContainer" style="display: none;">
<div class="progress-bar" id="progressBar"></div>
</div>
<canvas id="gameCanvas" class="race-canvas" width="800" height="500"></canvas>
<div class="controls" style="display: none;" id="gameControls">
<button class="btn" id="pauseBtn">Пауза</button>
<button class="btn secondary" id="backToMenuBtn">В меню</button>
</div>
</div>
</div>
<div class="game-over" id="gameOver">
<h2 id="resultTitle">Испытание пройдено!</h2>
<p>Ваш результат:</p>
<div id="resultStats">
<p>Скорость: <span id="finalSpeed">0</span> км/ч</p>
<p>Дистанция: <span id="finalDistance">0</span> м</p>
<p>Время: <span id="finalTime">0</span> сек</p>
</div>
<button class="btn" id="continueBtn">Продолжить</button>
<button class="btn secondary" id="menuBtn">В меню</button>
</div>
<script>
// Объект состояния игры
const gameState = {
difficulty: null,
isPlaying: false,
score: 0,
distance: 0,
time: 0,
speed: 0,
maxSpeed: 0,
completed: {
easy: false,
medium: false,
hard: false,
extreme: false
},
playerX: 100,
playerY: 250,
obstacles: [],
lastObstacleTime: 0,
obstacleInterval: 2000,
gameWidth: 800,
gameHeight: 500,
keys: {},
progress: 0,
blizzardActive: false,
blizzardSpeed: 0,
blizzardSize: 0,
blizzardDirection: 1,
blizzardInterval: null,
requiredProgress: 1000
};
// DOM элементы
const elements = {
mainMenu: document.getElementById('mainMenu'),
gameCanvas: document.getElementById('gameCanvas'),
gameInfo: document.getElementById('gameInfo'),
progressContainer: document.getElementById('progressContainer'),
progressBar: document.getElementById('progressBar'),
gameControls: document.getElementById('gameControls'),
gameOver: document.getElementById('gameOver'),
pauseBtn: document.getElementById('pauseBtn'),
backToMenuBtn: document.getElementById('backToMenuBtn'),
continueBtn: document.getElementById('continueBtn'),
menuBtn: document.getElementById('menuBtn'),
resultTitle: document.getElementById('resultTitle'),
resultStats: document.getElementById('resultStats'),
finalSpeed: document.getElementById('finalSpeed'),
finalDistance: document.getElementById('finalDistance'),
finalTime: document.getElementById('finalTime'),
speedDisplay: document.getElementById('speedDisplay'),
distanceDisplay: document.getElementById('distanceDisplay'),
timeDisplay: document.getElementById('timeDisplay'),
hardLevel: document.getElementById('hardLevel'),
extremeLevel: document.getElementById('extremeLevel'),
raceMode: document.getElementById('raceMode'),
particles: document.getElementById('particles')
};
// Инициализация игры
function initGame() {
// Создание снежинок
createSnowflakes();
// Настройка сложностей
document.querySelectorAll('.difficulty-item').forEach(item => {
if (!item.classList.contains('locked')) {
item.querySelector('button').addEventListener('click', () => {
const difficulty = item.getAttribute('data-difficulty');
startGame(difficulty);
});
}
});
// Кнопки управления
elements.pauseBtn.addEventListener('click', togglePause);
elements.backToMenuBtn.addEventListener('click', backToMenu);
elements.continueBtn.addEventListener('click', continueGame);
elements.menuBtn.addEventListener('click', backToMenu);
// Обработка клавиш
document.addEventListener('keydown', (e) => {
if (gameState.isPlaying) {
if (e.key === 'Escape') {
togglePause();
} else {
gameState.keys[e.key] = true;
}
}
});
document.addEventListener('keyup', (e) => {
gameState.keys[e.key] = false;
});
// Проверяем сохраненные прогрессы
const savedProgress = localStorage.getItem('sheregeshProgress');
if (savedProgress) {
const progress = JSON.parse(savedProgress);
gameState.completed = progress;
// Разблокируем уровни по прогрессу
if (progress.easy && progress.medium) {
elements.hardLevel.classList.remove('locked');
elements.hardLevel.querySelector('button').textContent = 'Начать';
}
if (progress.easy && progress.medium && progress.hard) {
elements.extremeLevel.classList.remove('locked');
elements.extremeLevel.querySelector('button').textContent = 'Начать';
}
if (progress.easy && progress.medium && progress.hard && progress.extreme) {
elements.raceMode.classList.remove('locked');
elements.raceMode.querySelector('button').textContent = 'Начать';
}
}
}
// Создание снежинок
function createSnowflakes() {
for (let i = 0; i < 100; i++) {
const snowflake = document.createElement('div');
snowflake.classList.add('snow');
// Рандомные параметры снежинок
const size = Math.random() * 5;
const opacity = Math.random() * 0.7 + 0.3;
const x = Math.random() * 100;
const duration = Math.random() * 10 + 5;
const delay = Math.random() * 10;
snowflake.style.width = `${size}px`;
snowflake.style.height = `${size}px`;
snowflake.style.opacity = opacity;
snowflake.style.left = `${x}vw`;
snowflake.style.animationDuration = `${duration}s`;
snowflake.style.animationDelay = `-${delay}s`;
elements.particles.appendChild(snowflake);
}
}
// Начало игры
function startGame(difficulty) {
gameState.difficulty = difficulty;
gameState.isPlaying = true;
gameState.score = 0;
gameState.distance = 0;
gameState.time = 0;
gameState.speed = 0;
gameState.maxSpeed = getMaxSpeed(difficulty);
gameState.playerX = 100;
gameState.playerY = 250;
gameState.obstacles = [];
gameState.lastObstacleTime = 0;
gameState.progress = 0;
gameState.blizzardActive = difficulty === 'extreme';
gameState.blizzardSpeed = 0;
gameState.blizzardSize = 0;
gameState.blizzardDirection = 1;
gameState.requiredProgress = getRequiredProgress(difficulty);
// Настройка интервала препятствий
gameState.obstacleInterval = getObstacleInterval(difficulty);
// Скрытие меню, показ игры
elements.mainMenu.style.display = 'none';
elements.gameCanvas.style.display = 'block';
elements.gameInfo.style.display = 'flex';
elements.gameControls.style.display = 'flex';
// Для экстрима показываем прогресс
if (difficulty === 'extreme') {
elements.progressContainer.style.display = 'block';
} else {
elements.progressContainer.style.display = 'none';
}
// Настройка canvas
const ctx = elements.gameCanvas.getContext('2d');
ctx.imageSmoothingEnabled = true;
// Запуск игрового цикла
gameState.lastTime = Date.now();
gameState.gameLoop = requestAnimationFrame(updateGame);
// Для бурана
if (gameState.blizzardActive) {
startBlizzard();
}
}
// Получение максимальной скорости в зависимости от сложности
function getMaxSpeed(difficulty) {
switch(difficulty) {
case 'easy': return 60;
case 'medium': return 100;
case 'hard': return 140;
case 'extreme': return 180;
case 'race': return 120;
default: return 60;
}
}
// Получение интервала между препятствиями
function getObstacleInterval(difficulty) {
switch(difficulty) {
case 'easy': return 3000;
case 'medium': return 2000;
case 'hard': return 1500;
case 'extreme': return 1200;
case 'race': return 1800;
default: return 2000;
}
}
// Получение необходимого прогресса для завершения уровня
function getRequiredProgress(difficulty) {
switch(difficulty) {
case 'easy': return 500;
case 'medium': return 800;
case 'hard': return 1200;
case 'extreme': return 1500;
case 'race': return 1000;
default: return 500;
}
}
// Запуск бурана
function startBlizzard() {
gameState.blizzardInterval = setInterval(() => {
if (gameState.blizzardDirection === 1 && gameState.blizzardSize < 100) {
gameState.blizzardSpeed += 1;
gameState.blizzardSize += 1;
} else if (gameState.blizzardDirection === 1 && gameState.blizzardSize >= 100) {
gameState.blizzardDirection = -1;
} else if (gameState.blizzardDirection === -1 && gameState.blizzardSize > 0) {
gameState.blizzardSpeed -= 0.5;
gameState.blizzardSize -= 0.5;
} else {
gameState.blizzardDirection = 1;
}
}, 100);
}
// Остановка бурана
function stopBlizzard() {
if (gameState.blizzardInterval) {
clearInterval(gameState.blizzardInterval);
gameState.blizzardInterval = null;
}
}
// Игровой цикл
function updateGame() {
const now = Date.now();
const deltaTime = (now - gameState.lastTime) / 1000;
gameState.lastTime = now;
if (!gameState.isPaused) {
// Обновление состояния игры
updateGameState(deltaTime);
// Отрисовка игры
renderGame();
// Проверка условий завершения
if (gameState.difficulty === 'extreme' || gameState.difficulty === 'race') {
if (gameState.progress >= gameState.requiredProgress) {
completeLevel();
return;
}
}
// Для других уровней просто по времени
if (gameState.difficulty !== 'extreme' && gameState.time >= 60) {
completeLevel();
return;
}
}
gameState.gameLoop = requestAnimationFrame(updateGame);
}
// Обновление состояния игры
function updateGameState(deltaTime) {
// Увеличение времени и дистанции
gameState.time += deltaTime;
// Управление скоростью
if (gameState.keys['ArrowUp'] || gameState.keys['w']) {
gameState.speed = Math.min(gameState.speed + 10 * deltaTime, gameState.maxSpeed);
} else if (gameState.keys['ArrowDown'] || gameState.keys['s']) {
gameState.speed = Math.max(gameState.speed - 15 * deltaTime, 0);
} else {
// Постепенное замедление
gameState.speed = Math.max(gameState.speed - 5 * deltaTime, 0);
}
// Изменение положения игрока по вертикали
if (gameState.keys['ArrowLeft'] || gameState.keys['a']) {
gameState.playerX = Math.max(gameState.playerX - 200 * deltaTime, 50);
}
if (gameState.keys['ArrowRight'] || gameState.keys['d']) {
gameState.playerX = Math.min(gameState.playerX + 200 * deltaTime, gameState.gameWidth - 50);
}
// Увеличение дистанции в зависимости от скорости
gameState.distance += gameState.speed * deltaTime;
// Обновление препятствий
updateObstacles(deltaTime);
// Для экстремального режима - обновление прогресса
if (gameState.difficulty === 'extreme') {
gameState.progress += gameState.speed * deltaTime * 0.1;
elements.progressBar.style.width = `${Math.min((gameState.progress / gameState.requiredProgress) * 100, 100)}%`;
// Проверка поражения от бурана
if (gameState.blizzardActive && gameState.speed < gameState.blizzardSpeed) {
endGame(false);
return;
}
} else if (gameState.difficulty === 'race') {
gameState.progress += gameState.speed * deltaTime * 0.2;
}
// Обновление UI
elements.speedDisplay.textContent = Math.round(gameState.speed);
elements.distanceDisplay.textContent = Math.round(gameState.distance);
elements.timeDisplay.textContent = Math.round(gameState.time);
}
// Обновление препятствий
function updateObstacles(deltaTime) {
// Создание нового препятствия
if (Date.now() - gameState.lastObstacleTime > gameState.obstacleInterval) {
createObstacle();
gameState.lastObstacleTime = Date.now();
}
// Обновление позиций препятствий
for (let i = gameState.obstacles.length - 1; i >= 0; i--) {
const obstacle = gameState.obstacles[i];
obstacle.x -= gameState.speed * deltaTime;
// Проверка столкновения
if (checkCollision(gameState.playerX, gameState.playerY, obstacle.x, obstacle.y, obstacle.width, obstacle.height)) {
endGame(false);
break;
}
// Удаление препятствий за пределами экрана
if (obstacle.x + obstacle.width < 0) {
gameState.obstacles.splice(i, 1);
gameState.score += 10;
}
}
}
// Создание нового препятствия
function createObstacle() {
const types = ['tree', 'rock', 'jump'];
const type = types[Math.floor(Math.random() * types.length)];
const yPositions = [300, 350, 400];
const y = yPositions[Math.floor(Math.random() * yPositions.length)];
let width, height, x;
if (type === 'tree') {
width = 40;
height = 80;
x = gameState.gameWidth + Math.random() * 100;
} else if (type === 'rock') {
width = 60;
height = 40;
x = gameState.gameWidth + Math.random() * 100;
} else if (type === 'jump') {
width = 100;
height = 20;
x = gameState.gameWidth + Math.random() * 150;
}
gameState.obstacles.push({
type,
x,
y,
width,
height
});
}
// Проверка столкновения
function checkCollision(px, py, ox, oy, ow, oh) {
// Простая проверка столкновения AABB
return px < ox + ow &&
px + 40 > ox &&
py < oy + oh &&
py + 60 > oy;
}
// Отрисовка игры
function renderGame() {
const ctx = elements.gameCanvas.getContext('2d');
ctx.clearRect(0, 0, gameState.gameWidth, gameState.gameHeight);
// Рисуем фон
drawBackground(ctx);
// Рисуем препятствия
drawObstacles(ctx);
// Рисуем игрока
drawPlayer(ctx);
// Для экстрима - рисуем буран
if (gameState.blizzardActive) {
drawBlizzard(ctx);
}
}
// Отрисовка фона
function drawBackground(ctx) {
// Небо
const skyGradient = ctx.createLinearGradient(0, 0, 0, gameState.gameHeight);
skyGradient.addColorStop(0, '#87CEEB');
skyGradient.addColorStop(1, '#E0F7FA');
ctx.fillStyle = skyGradient;
ctx.fillRect(0, 0, gameState.gameWidth, gameState.gameHeight);
// Снег (земля)
ctx.fillStyle = 'white';
ctx.fillRect(0, gameState.gameHeight - 100, gameState.gameWidth, 100);
// Горы на заднем фоне
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
for (let i = 0; i < 4; i++) {
const x = i * 200 + (gameState.distance % 200);
drawMountain(ctx, x, gameState.gameHeight - 100);
}
}
// Отрисовка одной горы
function drawMountain(ctx, x, y) {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + 100, y - 100);
ctx.lineTo(x + 200, y);
ctx.fill();
}
// Отрисовка препятствий
function drawObstacles(ctx) {
gameState.obstacles.forEach(obstacle => {
if (obstacle.type === 'tree') {
ctx.fillStyle = '#8B4513';
ctx.fillRect(obstacle.x, obstacle.y, 10, obstacle.height);
ctx.fillStyle = '#228B22';
ctx.beginPath();
ctx.arc(obstacle.x + 5, obstacle.y - 10, 20, 0, Math.PI * 2);
ctx.fill();
} else if (obstacle.type === 'rock') {
ctx.fillStyle = '#808080';
ctx.beginPath();
ctx.arc(obstacle.x + obstacle.width/2, obstacle.y + obstacle.height/2, obstacle.width/2, 0, Math.PI * 2);
ctx.fill();
} else if (obstacle.type === 'jump') {
ctx.fillStyle = '#A0522D';
ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
}
});
}
// Отрисовка игрока
function drawPlayer(ctx) {
ctx.fillStyle = '#FF0000';
ctx.beginPath();
// Туловище
ctx.moveTo(gameState.playerX, gameState.playerY);
ctx.lineTo(gameState.playerX - 20, gameState.playerY + 40);
ctx.lineTo(gameState.playerX + 20, gameState.playerY + 40);
ctx.closePath();
ctx.fill();
// Голова
ctx.fillStyle = '#FFD700';
ctx.beginPath();
ctx.arc(gameState.playerX, gameState.playerY - 10, 10, 0, Math.PI * 2);
ctx.fill();
}
// Отрисовка бурана
function drawBlizzard(ctx) {
ctx.fillStyle = `rgba(255, 255, 255, ${gameState.blizzardSize/100 * 0.7})`;
ctx.fillRect(0, 0, gameState.gameWidth, gameState.gameHeight);
// Текст скорости бурана
ctx.fillStyle = 'red';
ctx.font = '20px Montserrat';
ctx.fillText(`Буран: ${Math.round(gameState.blizzardSpeed)} км/ч`, 20, 30);
ctx.fillText(`Ваша скорость: ${Math.round(gameState.speed)} км/ч`, 20, 60);
}
// Пауза игры
function togglePause() {
gameState.isPaused = !gameState.isPaused;
elements.pauseBtn.textContent = gameState.isPaused ? 'Продолжить' : 'Пауза';
if (gameState.isPaused) {
cancelAnimationFrame(gameState.gameLoop);
} else {
gameState.lastTime = Date.now();
gameState.gameLoop = requestAnimationFrame(updateGame);
}
}
// Завершение уровня
function completeLevel() {
endGame(true);
}
// Конец игры
function endGame(isSuccess) {
cancelAnimationFrame(gameState.gameLoop);
gameState.isPlaying = false;
if (gameState.blizzardInterval) {
stopBlizzard();
}
// Обновление UI
elements.finalSpeed.textContent = Math.round(gameState.speed);
elements.finalDistance.textContent = Math.round(gameState.distance);
elements.finalTime.textContent = Math.round(gameState.time);
if (isSuccess) {
elements.resultTitle.textContent = 'Испытание пройдено!';
// Обновляем прогресс
gameState.completed[gameState.difficulty] = true;
localStorage.setItem('sheregeshProgress', JSON.stringify(gameState.completed));
// Разблокируем следующие уровни
if (gameState.difficulty === 'easy' && !gameState.completed.medium) {
elements.hardLevel.classList.remove('locked');
elements.hardLevel.querySelector('button').textContent = 'Начать';
}
if (gameState.difficulty === 'medium' && !gameState.completed.hard) {
elements.extremeLevel.classList.remove('locked');
elements.extremeLevel.querySelector('button').textContent = 'Начать';
}
if (gameState.difficulty === 'hard' && !gameState.completed.extreme) {
elements.raceMode.classList.remove('locked');
elements.raceMode.querySelector('button').textContent = 'Начать';
}
} else {
elements.resultTitle.textContent = gameState.blizzardActive && gameState.speed < gameState.blizzardSpeed ?
'Буран вас настиг!' : 'Вы упали!';
}
// Показываем экран завершения
elements.gameOver.style.display = 'block';
}
// Возврат в меню
function backToMenu() {
if (gameState.isPlaying) {
cancelAnimationFrame(gameState.gameLoop);
gameState.isPlaying = false;
}
if (gameState.blizzardInterval) {
stopBlizzard();
}
elements.mainMenu.style.display = 'block';
elements.gameCanvas.style.display = 'none';
elements.gameInfo.style.display = 'none';
elements.gameControls.style.display = 'none';
elements.progressContainer.style.display = 'none';
elements.gameOver.style.display = 'none';
}
// Продолжение игры (после прохождения уровня)
function continueGame() {
elements.gameOver.style.display = 'none';
backToMenu();
}
// Запуск игры при загрузке страницы
window.addEventListener('load', initGame);
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: absolute; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">This website has been generated by <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
</html>