Добро пожаловать в учебник по созданию игры Snake с использованием JavaScript и HTML. Я покажу вам, как создать базовую игру «Змейка» — классику, которая уже много лет пользуется популярностью у геймеров.

Если вы заинтересованы в изучении основ веб-разработки, хотите изучить игровую механику или просто хотите написать код для этой вечной игры, это руководство будет вам полезно. Я разберу каждый шаг, предоставлю необходимые фрагменты кода и объясню их логику.

К концу этого руководства у вас будет функциональная базовая игра Snake, в которую вы сможете играть прямо в браузере. Кроме того, вы получите представление о том, как JavaScript и HTML работают вместе для создания интерактивного веб-контента.

Итак, если вы готовы погрузиться в основы разработки игр и улучшить свои навыки программирования, давайте начнем. Никакой шумихи, никаких излишеств — просто простое пошаговое руководство по созданию собственной игры «Змейка». Давайте прыгать! 🕹️

Прежде чем мы начнем:

Прежде чем мы углубимся в создание игры Snake, давайте удостоверимся, что у вас есть необходимые инструменты.

1.Веб-браузер. Вам понадобится современный веб-браузер, например Google Chrome, Mozilla Firefox или Microsoft Edge, чтобы запустить и протестировать игру Snake.

2. Текстовый редактор. Выберите текстовый редактор или интегрированную среду разработки (IDE) для написания и редактирования кода HTML, CSS и JavaScript. Подойдет Visual Studio Code, Sublime Text или даже простой блокнот.

3. Создайте каталог проекта: начните с создания нового каталога на своем компьютере. Этот каталог будет домом для вашего игрового проекта Snake. Вы можете назвать это что-то вроде «SnakeGame».

4. Создайте файл HTML:В каталоге проекта создайте новый файл с именем `index.html`. Этот файл будет содержать весь код вашей игры.

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Snake Game</title>
    <style>
        /* CSS code for styling the game board and elements */
        #game-board {
            width: 300px;
            height: 300px;
            border: 1px solid black;
            position: relative;
        }
        .snake-part {
            width: 20px;
            height: 20px;
            background-color: green;
            position: absolute;
        }
        #food {
            width: 20px;
            height: 20px;
            background-color: red;
            position: absolute;
        }
    </style>
</head>
<body>
    <!-- The game board container -->
    <div id="game-board"></div>

    <script>
        // Write the JavaScript code for the next steps below
      
    </script>
</body>
</html>

Теперь игра:

  1. Инициализация игры:

    Мы начнем с инициализации игрового поля, начального положения Змеи, начального положения еды и начального направления Змеи.
<script>
    // JavaScript code for the Snake game
     // ... (Previous code)
    // Game initialization
    const gameBoard = document.getElementById("game-board");
    let snake = [{ x: 10, y: 10 }]; // Initial position of the snake
    let food = { x: 5, y: 5 }; // Initial position of the food
    let direction = "right"; // Initial direction of the snake

    // Rest of the JavaScript code
</script>

В этой части мы используем переменные JavaScript для отслеживания состояния игры. `snake` — это массив, представляющий положение змеи (изначально с одним элементом), `food` – объект, представляющий положение еды, а `direction` – строка, представляющая направление, в котором движется змея.

2.Обновите игровое поле:

Мы создадим функцию под названием `updateGameBoard`, которая обновляет визуальное отображение игрового поля, перерисовывая змею и еду на их текущих позициях.

<script>
    // JavaScript code for the Snake game

    // ... (Previous code)

    // Function to update the game board
    function updateGameBoard() {
        gameBoard.innerHTML = ""; // Clear the previous frame

        // Draw the snake
        for (let i = 0; i < snake.length; i++) {
            const snakePart = document.createElement("div");
            snakePart.classList.add("snake-part");
            snakePart.style.left = snake[i].x * 20 + "px";
            snakePart.style.top = snake[i].y * 20 + "px";
            gameBoard.appendChild(snakePart);
        }

        // Draw the food
        const foodElement = document.createElement("div");
        foodElement.id = "food";
        foodElement.style.left = food.x * 20 + "px";
        foodElement.style.top = food.y * 20 + "px";
        gameBoard.appendChild(foodElement);
    }

    // Rest of the JavaScript code
</script>

Функция `updateGameBoard` очищает предыдущий кадр, устанавливая `innerHTML` игрового поля в пустую строку. Затем он создает элементы `div` для представления каждой части Змеи и еды, размещает их на игровом поле и добавляет к игровому полю.

3. Переместите змейку:

Мы создадим функцию под названием «moveSnake», которая обрабатывает движение Змеи в зависимости от текущего направления и обновляет ее положение.

<script>
    // JavaScript code for the Snake game

    // ... (Previous code)

    // Function to move the snake
    function moveSnake() {
        const newHead = { x: snake[0].x, y: snake[0].y };

        // Update the position of the new head based on the current direction
        switch (direction) {
            case "up":
                newHead.y -= 1;
                break;
            case "down":
                newHead.y += 1;
                break;
            case "left":
                newHead.x -= 1;
                break;
            case "right":
                newHead.x += 1;
                break;
        }

        snake.unshift(newHead); // Add the new head to the front

        // Check if the snake ate the food
        if (newHead.x === food.x && newHead.y === food.y) {
            // Generate new food at a random position
            food = {
                x: Math.floor(Math.random() * 15),
                y: Math.floor(Math.random() * 15),
            };
        } else {
            // Snake didn't eat the food, remove the tail
            snake.pop();
        }
    }

    // Rest of the JavaScript code
</script>

Функция moveSnake вычисляет новое положение головы Змеи на основе текущего направления. Если новое положение головы совпадает с положением еды, Змея растет (съедает пищу) и создается новая позиция еды. Если пища не съедена, хвост Змеи убирается для имитации движения.

4. Проверить наличие столкновений и окончания игры:

Мы создадим функцию под названием `checkGameOver`, которая проверяет наличие столкновений как с границами игрового поля, так и с собственным телом Змеи, что приводит к состоянию окончания игры.

<script>
    // JavaScript code for the Snake game

    // ... (Previous code)

    // Function to check if the game is over
    function checkGameOver() {
        const head = snake[0];

        // Check collision with walls
        if (head.x < 0 || head.y < 0 || head.x >= 15 || head.y >= 15) {
            clearInterval(gameInterval);
            alert("Game Over! You hit the wall.");
        }

        // Check collision with itself
        for (let i = 1; i < snake.length; i++) {
            if (snake[i].x === head.x && snake[i].y === head.y) {
                clearInterval(gameInterval);
                alert("Game Over! You collided with yourself.");
            }
        }
    }

    // Rest of the JavaScript code
</script>

Функция `checkGameOver` проверяет, находится ли голова Змеи за пределами игрового поля или сталкивается с собственным телом. Если происходит столкновение, интервал игрового цикла сбрасывается, и отображается предупреждение, уведомляющее игрока об окончании игры.

5. Обработка нажатий клавиш:

Мы создадим функцию с именем `handleKeyPress`, которая прослушивает нажатия клавиш со стрелками и соответствующим образом обновляет переменную `direction`.

<script>
    // JavaScript code for the Snake game

    // ... (Previous code)

    // Function to handle key presses
    function handleKeyPress(event) {
        // Update the direction based on arrow key presses
        switch (event.key) {
            case "ArrowUp":
                direction = "up";
                break;
            case "ArrowDown":
                direction = "down";
                break;
            case "ArrowLeft":
                direction = "left";
                break;
            case "ArrowRight":
                direction = "right";
                break;
        }
    }

    // Add event listener for key presses
    document.addEventListener("keydown", handleKeyPress);

    // Rest of the JavaScript code
</script>

Функция `handleKeyPress` слушает события нажатия клавиши (в частности, нажатия клавиши со стрелкой) и обновляет переменную `direction` на соответствующее направление («вверх», «вниз», «влево» или «вправо»).

6. Игровой цикл:

Мы настроим игровой цикл, используя `setInterval`, чтобы непрерывно перемещать Змею, проверять наличие столкновений и обновлять игровое поле.

<script>
    // JavaScript code for the Snake game

    // ... (Previous code)

    // Game loop: Moves the snake, checks game over conditions, and updates the game board
    const gameInterval = setInterval(() => {
        moveSnake();
        checkGameOver();
        updateGameBoard();
    }, 200); // Interval for game updates (milliseconds)

    // Rest of the JavaScript code
</script>

Игровой цикл вызывает функции moveSnake, checkGameOver и updateGameBoard с регулярными интервалами (200 миллисекунд в этом примере) для имитации непрерывного движения, проверки столкновений и обновления визуальных эффектов игрового поля.

И готово!

Проверьте свою установку:

  • Сохраните файл index.html.
  • Откройте файл index.html в веб-браузере.
  • Вы увидите игровое поле с элементами Змеи и еды.

Теперь вы готовы протестировать игру в своем браузере и насладиться магией Змейки! 🐍🕹️

Полный код:

<!-- index.html -->
<!DOCTYPE html>
<html>
  <head>
    <title>Snake Game</title>
    <style>
      /* CSS code for styling the game board and elements */
      #game-board {
        width: 300px;
        height: 300px;
        border: 1px solid black;
        position: relative;
      }
      .snake-part {
        width: 20px;
        height: 20px;
        background-color: green;
        position: absolute;
      }
      #food {
        width: 20px;
        height: 20px;
        background-color: red;
        position: absolute;
      }
    </style>
  </head>
  <body>
    <!-- The game board container -->
    <div id="game-board"></div>

    <script>
      // Write the JavaScript code for the next steps below
      // Game initialization
      const gameBoard = document.getElementById("game-board");
      let snake = [{ x: 10, y: 10 }]; // Initial position of the snake
      let food = { x: 5, y: 5 }; // Initial position of the food
      let direction = "right"; // Initial direction of the snake

      // Function to update the game board
      function updateGameBoard() {
        gameBoard.innerHTML = ""; // Clear the previous frame

        // Draw the snake
        for (let i = 0; i < snake.length; i++) {
          const snakePart = document.createElement("div");
          snakePart.classList.add("snake-part");
          snakePart.style.left = snake[i].x * 20 + "px";
          snakePart.style.top = snake[i].y * 20 + "px";
          gameBoard.appendChild(snakePart);
        }

        // Draw the food
        const foodElement = document.createElement("div");
        foodElement.id = "food";
        foodElement.style.left = food.x * 20 + "px";
        foodElement.style.top = food.y * 20 + "px";
        gameBoard.appendChild(foodElement);
      }

      // Function to move the snake
      function moveSnake() {
        const newHead = { x: snake[0].x, y: snake[0].y };

        // Update the position of the new head based on the current direction
        switch (direction) {
          case "up":
            newHead.y -= 1;
            break;
          case "down":
            newHead.y += 1;
            break;
          case "left":
            newHead.x -= 1;
            break;
          case "right":
            newHead.x += 1;
            break;
        }

        snake.unshift(newHead); // Add the new head to the front

        // Check if the snake ate the food
        if (newHead.x === food.x && newHead.y === food.y) {
          // Generate new food at a random position
          food = {
            x: Math.floor(Math.random() * 15),
            y: Math.floor(Math.random() * 15),
          };
        } else {
          // Snake didn't eat the food, remove the tail
          snake.pop();
        }
      }

      function checkGameOver() {
        const head = snake[0];

        // Check collision with walls
        if (head.x < 0 || head.y < 0 || head.x >= 15 || head.y >= 15) {
          clearInterval(gameInterval);
          alert("Game Over! You hit the wall.");
        }

        // Check collision with itself
        for (let i = 1; i < snake.length; i++) {
          if (snake[i].x === head.x && snake[i].y === head.y) {
            clearInterval(gameInterval);
            alert("Game Over! You collided with yourself.");
          }
        }
      }

      // Function to handle key presses
      function handleKeyPress(event) {
        // Update the direction based on arrow key presses
        switch (event.key) {
          case "ArrowUp":
            direction = "up";
            break;
          case "ArrowDown":
            direction = "down";
            break;
          case "ArrowLeft":
            direction = "left";
            break;
          case "ArrowRight":
            direction = "right";
            break;
        }
      }

      // Add event listener for key presses
      document.addEventListener("keydown", handleKeyPress);

      const gameInterval = setInterval(() => {
        moveSnake();
        checkGameOver();
        updateGameBoard();
      }, 200); // Interval for game updates (milliseconds)
      
    </script>
  </body>
</html>

Также на JSFiddle: https://jsfiddle.net/j0hnskot/zgt139kd/