HTML для игр

Сложность: Продвинутый

HTML Игры

Создание интерактивных игр с использованием HTML, Canvas и JavaScript.

1. Игра "Змейка" на Canvas

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Змейка - HTML5 Игра</title>
    <style>
        body {
            margin: 0;
            padding: 20px;
            background: linear-gradient(135deg, #1e3c72, #2a5298);
            font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            color: white;
        }
        
        .game-container {
            text-align: center;
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            border-radius: 20px;
            padding: 30px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
            border: 1px solid rgba(255, 255, 255, 0.2);
        }
        
        h1 {
            margin-bottom: 10px;
            font-size: 2.5em;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
        }
        
        .score-container {
            display: flex;
            justify-content: space-around;
            margin: 20px 0;
            font-size: 1.2em;
        }
        
        .score-item {
            background: rgba(255, 255, 255, 0.2);
            padding: 10px 20px;
            border-radius: 10px;
            min-width: 120px;
        }
        
        canvas {
            border: 3px solid rgba(255, 255, 255, 0.3);
            border-radius: 10px;
            background: rgba(0, 0, 0, 0.3);
            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
        }
        
        .controls {
            margin: 20px 0;
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 10px;
            max-width: 300px;
            margin-left: auto;
            margin-right: auto;
        }
        
        button {
            background: rgba(255, 255, 255, 0.2);
            border: 2px solid rgba(255, 255, 255, 0.3);
            color: white;
            padding: 15px;
            border-radius: 10px;
            cursor: pointer;
            font-size: 16px;
            font-weight: bold;
            transition: all 0.3s ease;
        }
        
        button:hover {
            background: rgba(255, 255, 255, 0.3);
            transform: translateY(-2px);
        }
        
        .game-over {
            display: none;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.9);
            padding: 40px;
            border-radius: 15px;
            text-align: center;
            z-index: 10;
        }
        
        .instructions {
            margin-top: 20px;
            background: rgba(255, 255, 255, 0.1);
            padding: 15px;
            border-radius: 10px;
            font-size: 0.9em;
        }
        
        .mobile-controls {
            display: none;
            grid-template-columns: repeat(3, 1fr);
            grid-template-rows: repeat(3, 1fr);
            gap: 10px;
            margin-top: 20px;
            max-width: 200px;
            margin-left: auto;
            margin-right: auto;
        }
        
        @media (max-width: 768px) {
            .mobile-controls {
                display: grid;
            }
            
            .controls {
                display: none;
            }
        }
    </style>
</head>
<body>
    <div class="game-container">
        <h1>? Змейка</h1>
        
        <div class="score-container">
            <div class="score-item">
                <div>ОЧКИ</div>
                <div id="score">0</div>
            </div>
            <div class="score-item">
                <div>РЕКОРД</div>
                <div id="highScore">0</div>
            </div>
        </div>
        
        <canvas id="gameCanvas" width="400" height="400"></canvas>
        
        <div class="controls">
            <div></div>
            <button onclick="changeDirection("UP")">⬆️ ВВЕРХ</button>
            <div></div>
            <button onclick="changeDirection("LEFT")">⬅️ ЛЕВО</button>
            <button onclick="togglePause()" id="pauseBtn">⏸️ ПАУЗА</button>
            <button onclick="changeDirection("RIGHT")">➡️ ПРАВО</button>
            <div></div>
            <button onclick="changeDirection("DOWN")">⬇️ ВНИЗ</button>
            <div></div>
        </div>
        
        <div class="mobile-controls">
            <div></div>
            <button onclick="changeDirection("UP")">⬆️</button>
            <div></div>
            <button onclick="changeDirection("LEFT")">⬅️</button>
            <button onclick="togglePause()" id="mobilePauseBtn">⏸️</button>
            <button onclick="changeDirection("RIGHT")">➡️</button>
            <div></div>
            <button onclick="changeDirection("DOWN")">⬇️</button>
            <div></div>
        </div>
        
        <div class="instructions">
            <p>? Управление: Стрелки клавиатуры или кнопки на экране</p>
            <p>? Собирайте еду, чтобы расти и набирать очки</p>
            <p>? Избегайте стен и собственного хвоста</p>
        </div>
    </div>
    
    <div class="game-over" id="gameOver">
        <h2 style="color: #ff6b6b;">ИГРА ОКОНЧЕНА!</h2>
        <p>Ваш счет: <span id="finalScore">0</span></p>
        <p>Рекорд: <span id="finalHighScore">0</span></p>
        <button onclick="resetGame()" style="background: #4ecdc4; margin: 10px;">
            ? ИГРАТЬ СНОВА
        </button>
    </div>

    <script>
        const canvas = document.getElementById("gameCanvas");
        const ctx = canvas.getContext("2d");
        const scoreElement = document.getElementById("score");
        const highScoreElement = document.getElementById("highScore");
        const gameOverScreen = document.getElementById("gameOver");
        const finalScoreElement = document.getElementById("finalScore");
        const finalHighScoreElement = document.getElementById("finalHighScore");
        
        // Константы игры
        const GRID_SIZE = 20;
        const TILE_COUNT = canvas.width / GRID_SIZE;
        
        // Переменные игры
        let snake = [{x: 10, y: 10}];
        let food = {};
        let dx = 0;
        let dy = 0;
        let score = 0;
        let highScore = localStorage.getItem("snakeHighScore") || 0;
        let gameRunning = false;
        let gamePaused = false;
        let gameLoop;
        
        // Инициализация игры
        function initGame() {
            snake = [{x: 10, y: 10}];
            generateFood();
            dx = 0;
            dy = 0;
            score = 0;
            updateScore();
            highScoreElement.textContent = highScore;
            gameRunning = true;
            gamePaused = false;
            gameOverScreen.style.display = "none";
        }
        
        // Генерация еды
        function generateFood() {
            food = {
                x: Math.floor(Math.random() * TILE_COUNT),
                y: Math.floor(Math.random() * TILE_COUNT)
            };
            
            // Проверка, чтобы еда не появилась на змейке
            for (let segment of snake) {
                if (segment.x === food.x && segment.y === food.y) {
                    return generateFood();
                }
            }
        }
        
        // Основной игровой цикл
        function gameUpdate() {
            if (gamePaused || !gameRunning) return;
            
            moveSnake();
            
            if (checkCollision()) {
                gameOver();
                return;
            }
            
            if (checkFoodCollision()) {
                score += 10;
                updateScore();
                generateFood();
            }
            
            drawGame();
        }
        
        // Движение змейки
        function moveSnake() {
            const head = {x: snake[0].x + dx, y: snake[0].y + dy};
            snake.unshift(head);
            
            if (!checkFoodCollision()) {
                snake.pop();
            }
        }
        
        // Проверка столкновений
        function checkCollision() {
            const head = snake[0];
            
            // Столкновение со стенами
            if (head.x < 0 || head.x >= TILE_COUNT || head.y < 0 || head.y >= TILE_COUNT) {
                return true;
            }
            
            // Столкновение с собой
            for (let i = 1; i < snake.length; i++) {
                if (head.x === snake[i].x && head.y === snake[i].y) {
                    return true;
                }
            }
            
            return false;
        }
        
        // Проверка столкновения с едой
        function checkFoodCollision() {
            const head = snake[0];
            return head.x === food.x && head.y === food.y;
        }
        
        // Отрисовка игры
        function drawGame() {
            // Очистка canvas
            ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            
            // Отрисовка сетки
            ctx.strokeStyle = "rgba(255, 255, 255, 0.05)";
            for (let i = 0; i < TILE_COUNT; i++) {
                for (let j = 0; j < TILE_COUNT; j++) {
                    ctx.strokeRect(i * GRID_SIZE, j * GRID_SIZE, GRID_SIZE, GRID_SIZE);
                }
            }
            
            // Отрисовка змейки
            snake.forEach((segment, index) => {
                if (index === 0) {
                    // Голова змейки
                    ctx.fillStyle = "#4ecdc4";
                    ctx.fillRect(segment.x * GRID_SIZE, segment.y * GRID_SIZE, GRID_SIZE, GRID_SIZE);
                    
                    // Глаза
                    ctx.fillStyle = "#2c3e50";
                    const eyeSize = GRID_SIZE / 5;
                    const offset = GRID_SIZE / 4;
                    
                    // Левый глаз
                    ctx.fillRect(
                        segment.x * GRID_SIZE + offset,
                        segment.y * GRID_SIZE + offset,
                        eyeSize, eyeSize
                    );
                    
                    // Правый глаз
                    ctx.fillRect(
                        segment.x * GRID_SIZE + GRID_SIZE - offset - eyeSize,
                        segment.y * GRID_SIZE + offset,
                        eyeSize, eyeSize
                    );
                } else {
                    // Тело змейки
                    const gradient = ctx.createLinearGradient(
                        segment.x * GRID_SIZE, segment.y * GRID_SIZE,
                        (segment.x + 1) * GRID_SIZE, (segment.y + 1) * GRID_SIZE
                    );
                    gradient.addColorStop(0, "#45b7d1");
                    gradient.addColorStop(1, "#96ceb4");
                    
                    ctx.fillStyle = gradient;
                    ctx.fillRect(segment.x * GRID_SIZE, segment.y * GRID_SIZE, GRID_SIZE, GRID_SIZE);
                    
                    // Внутренний контур
                    ctx.strokeStyle = "#2c3e50";
                    ctx.lineWidth = 1;
                    ctx.strokeRect(segment.x * GRID_SIZE, segment.y * GRID_SIZE, GRID_SIZE, GRID_SIZE);
                }
            });
            
            // Отрисовка еды
            const foodGradient = ctx.createRadialGradient(
                food.x * GRID_SIZE + GRID_SIZE/2, food.y * GRID_SIZE + GRID_SIZE/2, 0,
                food.x * GRID_SIZE + GRID_SIZE/2, food.y * GRID_SIZE + GRID_SIZE/2, GRID_SIZE/2
            );
            foodGradient.addColorStop(0, "#ff6b6b");
            foodGradient.addColorStop(1, "#ff8e8e");
            
            ctx.fillStyle = foodGradient;
            ctx.beginPath();
            ctx.arc(
                food.x * GRID_SIZE + GRID_SIZE/2,
                food.y * GRID_SIZE + GRID_SIZE/2,
                GRID_SIZE/2 - 1,
                0,
                Math.PI * 2
            );
            ctx.fill();
            
            // Блик на еде
            ctx.fillStyle = "rgba(255, 255, 255, 0.3)";
            ctx.beginPath();
            ctx.arc(
                food.x * GRID_SIZE + GRID_SIZE/3,
                food.y * GRID_SIZE + GRID_SIZE/3,
                GRID_SIZE/6,
                0,
                Math.PI * 2
            );
            ctx.fill();
        }
        
        // Обновление счета
        function updateScore() {
            scoreElement.textContent = score;
            if (score > highScore) {
                highScore = score;
                highScoreElement.textContent = highScore;
                localStorage.setItem("snakeHighScore", highScore);
            }
        }
        
        // Конец игры
        function gameOver() {
            gameRunning = false;
            finalScoreElement.textContent = score;
            finalHighScoreElement.textContent = highScore;
            gameOverScreen.style.display = "block";
        }
        
        // Смена направления
        function changeDirection(direction) {
            if (gamePaused) return;
            
            const goingUp = dy === -1;
            const goingDown = dy === 1;
            const goingRight = dx === 1;
            const goingLeft = dx === -1;
            
            switch (direction) {
                case "UP":
                    if (!goingDown) {
                        dx = 0;
                        dy = -1;
                    }
                    break;
                case "DOWN":
                    if (!goingUp) {
                        dx = 0;
                        dy = 1;
                    }
                    break;
                case "LEFT":
                    if (!goingRight) {
                        dx = -1;
                        dy = 0;
                    }
                    break;
                case "RIGHT":
                    if (!goingLeft) {
                        dx = 1;
                        dy = 0;
                    }
                    break;
            }
            
            if (!gameRunning && (dx !== 0 || dy !== 0)) {
                startGame();
            }
        }
        
        // Пауза/продолжение
        function togglePause() {
            if (!gameRunning) return;
            
            gamePaused = !gamePaused;
            const pauseBtn = document.getElementById("pauseBtn");
            const mobilePauseBtn = document.getElementById("mobilePauseBtn");
            
            if (gamePaused) {
                pauseBtn.textContent = "▶️ ПРОДОЛЖИТЬ";
                mobilePauseBtn.textContent = "▶️";
            } else {
                pauseBtn.textContent = "⏸️ ПАУЗА";
                mobilePauseBtn.textContent = "⏸️";
            }
        }
        
        // Сброс игры
        function resetGame() {
            initGame();
            startGame();
        }
        
        // Запуск игры
        function startGame() {
            if (gameLoop) {
                clearInterval(gameLoop);
            }
            gameRunning = true;
            gameLoop = setInterval(gameUpdate, 150);
        }
        
        // Обработка клавиатуры
        document.addEventListener("keydown", (e) => {
            switch (e.key) {
                case "ArrowUp":
                    e.preventDefault();
                    changeDirection("UP");
                    break;
                case "ArrowDown":
                    e.preventDefault();
                    changeDirection("DOWN");
                    break;
                case "ArrowLeft":
                    e.preventDefault();
                    changeDirection("LEFT");
                    break;
                case "ArrowRight":
                    e.preventDefault();
                    changeDirection("RIGHT");
                    break;
                case :
                    e.preventDefault();
                    togglePause();
                    break;
                case "Enter":
                    if (!gameRunning) {
                        resetGame();
                    }
                    break;
            }
        });
        
        // Инициализация при загрузке
        window.addEventListener("load", () => {
            initGame();
            drawGame();
            highScoreElement.textContent = highScore;
        });
    </script>
</body>
</html>