paint-brush
Возродите немного ностальгии: воссоздание игры «Змейка» с использованием HTML5 Canvas API и JavaScriptк@ssaurel
523 чтения
523 чтения

Возродите немного ностальгии: воссоздание игры «Змейка» с использованием HTML5 Canvas API и JavaScript

к Sylvain Saurel8m2024/01/21
Read on Terminal Reader

Слишком долго; Читать

Игра «Змея» — одна из величайших классических игр 90-х годов для мобильных телефонов Nokia. В этом уроке показано, как воссоздать его в HTML5.
featured image - Возродите немного ностальгии: воссоздание игры «Змейка» с использованием HTML5 Canvas API и JavaScript
Sylvain Saurel HackerNoon profile picture
0-item
1-item

Если вы никогда не играли в знаменитую игру «Змейка» , поднимите руку!


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


И все же было время, когда игра «Змейка» была игрой, в которую все владельцы мобильных телефонов проводили огромное количество времени. Да, тогда мы говорили не о смартфонах, а только о телефонах.


Это было хорошее время, как говорится, и Nokia популяризировала игру через свои мобильные устройства, которые тоже были эталоном. Сегодня от доминирования Nokia в мобильном мире и игры Snake мало что осталось.


Для тех, кто ностальгирует по этой игре – и я один из них, должен признаться – это руководство научит вас, как воссоздать ее для Интернета. Для этого я буду использовать Canvas API и JavaScript HTML5.


Это также возможность научиться использовать классы Javascript и создать эффективный игровой цикл для веб-игр.

Создание веб-страницы для нашей игры «Змейка»

Для начала мы собираемся создать веб-страницу, которая позволит нам играть в игру «Змейка», которую мы будем разрабатывать в этом уроке. Вскоре вы увидите, что эта веб-страница не представляет никаких трудностей. Два элемента div: один для заголовка страницы, а другой для отображения области, в которой будет двигаться змея.


Для этого я добавлю немного CSS , чтобы центрировать эти элементы управления, применив к ним фиксированную ширину:

Дизайн класса Змея

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


Наша Змея будет иметь следующие свойства:

  • bw и bh обозначают размер платы по ширине и высоте соответственно.
  • nbx и nby представляют количество ячеек, доступных на плате.
  • eltw и elth для представления размера элемента змеи по ширине и высоте.
  • dirx и diry , которые представляют вектор смещения змеи.
  • Marginx и Marginy добавляют небольшой запас к ширине и высоте элементов змеи, чтобы игрок мог видеть границу между каждым элементом змеи.
  • keyup , keydown , keyleft , keyright , которые хранят состояние движущихся стрелок в данный момент.
  • startftps хранит количество кадров в секунду, необходимое для перемещения змеи в начале игры.


В конце конструктора вызывается метод init для инициализации змеи в начале игры. Когда нужно запустить новую игру, просто вызовите этот метод инициализации еще раз.


Это дает нам следующий код для нашего класса Snake:

В методе init вы можете определить другие свойства змеи, например указатель на ее голову и указатель на ее хвост. Массив elements будет хранить все элементы змеи в данный момент. Свойство Points используется для хранения очков за текущую игру, а свойство level используется для определения количества накопленных очков для увеличения частоты кадров в игре. Чем выше количество кадров в секунду, тем быстрее будет двигаться змея.


Поскольку свойство fps представляет количество кадров в секунду, нам необходимо иметь свойство fpsinterval, значение которого равно результату деления 1 секунды (или 1000 миллисекунд) на желаемое количество кадров в секунду.

Принцип игры Змейка

Принцип игры «Змейка» прост: вам нужно направлять змею с помощью четырех стрелок направления так, чтобы она съела максимальное количество яблок, которые появляются на доске. Каждый раз, когда вы едите яблоко, змея увеличивается на один элемент. По мере того, как змея растет, вам будет трудно не коснуться ее собственного хвоста. Если вы этого не сделаете, вы проиграете, и счет снова начнется с нуля. Конечно, каждый раз, когда вы съедаете яблоко, вы получаете очко.


Стоит отметить, что версия Snake, которую мы собираемся реализовать, — это та версия, в которой прикосновение к краям доски не приводит к проигрышу. Это просто заставляет вас опрокинуться на противоположную сторону. Таким образом компания Nokia реализовала вторые версии игры «Змейка».


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


Это дает нам следующий метод генерации еды для нашего класса Snake:

Рендеринг змеи на экране

Наш класс Snake развивается, и теперь нам нужно создать метод для отрисовки змеи на экране. Нам также нужно будет отобразить количество очков игрока в данный момент времени и, наконец, отобразить яблоко, которое нужно съесть. Позиция яблока хранится в свойстве food класса Snake.


Чтобы отобразить Змею на экране, я использую Canvas API HTML5.


Я буду использовать примитивы рисования этого API для рисования прямоугольников, представляющих различные элементы змеи, а также яблоко, которое нужно съесть. Я применю к яблоку и змее разные цвета, чтобы игрок мог их различать.


Это дает следующий код для метода рисования нашего класса Snake:

Перемещение змеи

Теперь у нас есть змея, которую мы можем отобразить на экране. Это все очень хорошо, но нам нужно добавить поддержку движения змеи. Как объяснялось выше, змейка движется по координатному вектору (dirx, diry). Итак, каждый раз, когда мы вызываем метод перемещения, который я собираюсь здесь определить, змея будет перемещаться на одну и ту же величину.


В этом методе перемещения мы проверяем, что координаты головы змеи соответствуют координатам съедобного яблока. Если да, то змея только что съела яблоко. Игрок получает очко, но что более важно, нам нужно совершить четыре действия:


  1. Добавьте элемент к элементам змеи. Этот элемент становится новым хвостом.
  2. Создайте новое яблоко, вызвав функцию Genefood.
  3. Добавьте очко игроку.
  4. Если игрок проходит уровень, то мы обновляем количество отображаемых кадров в секунду, чтобы ускорить движение Змеи.


Тем не менее, в методе перемещения нам нужно проверить, не допустил ли игрок ошибку, коснувшись головой элемента змеи. В этом случае игра проиграна и мы начинаем заново! Для этого мы вызываем метод init класса Snake, представленный выше.


Теперь нам нужно завершить метод перемещения, фактически переместив змею. Для этого к координатам головы змеи добавляем dirx и diry. Это дает нам возможность добавить новую голову. Вы также заметите, что перемещение змеи осуществляется разумно: каждый раз удаляется хвост и добавляется новая голова. Это позволяет избежать необходимости обновлять положение всех элементов змеи.


В завершение не забудьте обновить новую головку. Кстати, вы также заметили, что когда голова змеи пересекает границу доски, мы заставляем ее переместиться на противоположную сторону доски. Это касается как ширины, так и длины.


Это дает нам следующий код для метода перемещения:

GameLoop нашей игры «Змейка»

Нашу Змею можно отобразить на экране. Нашу Змею можно переместить, вызвав ее метод перемещения. Чего нам не хватает?


Нам не хватает реализации GameLoop в нашей игре!


Без этого GameLoop, который будет вызывать методы перемещения и рисования через равные промежутки времени, Змея не сможет двигаться. Далее мы покажем вам, как правильно реализовать GameLoop в JavaScript, оставив браузеру возможность вызывать его, когда он сочтет нужным, чтобы не блокировать поток рендеринга веб-страницы игры.


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


В рамках нашего метода gameloop мы затем декоррелируем количество кадров в секунду, поддерживаемое браузером, от количества кадров в секунду, на которое мы хотим переместить нашу змею. Мы будем вызывать методы перемещения и рисования только тогда, когда находимся в пределах диапазона кадров в секунду, определенного ранее.


Важно обновить координаты вектора движения змеи в соответствии с состоянием четырех клавиш направления: вверх, вниз, влево и вправо.


Наконец, мы вызываем GameLoop, делегируя браузеру задачу выбора наилучшего момента для этого. Это дает нам следующий код для GameLoop:

Обработка взаимодействия пользователя со Snake

Чтобы Змея могла перемещаться в соответствии с клавишами направления, нажимаемыми игроком, мы используем события keydown и keyup. Для каждого из этих событий мы будем вызывать метод класса Snake. Логически это будет нажатие для события нажатия клавиши и нажатие для события нажатия клавиши.


Мы обновляем значение связанных свойств класса Snake в соответствии с тем, что игрок делает с этими ключами. Как видите, мы не блокируем игру, обновляя положение змеи напрямую. Вместо этого мы обновляем состояние в методе gameloop, который вызывается через регулярные промежутки времени.

Сборка различных компонентов Snake

Чтобы завершить эту игру «Змейка», нам нужно собрать различные элементы. Мы получаем объект Canvas по его идентификатору. Затем мы получаем 2D-контекст, связанный с этим Canvas. Примените желаемые размеры. Мы создаем объект Snake, передавая в качестве параметров различные ожидаемые значения, включая количество ячеек на доске.


Добавьте прослушиватели событий keydown и keyup.


Наконец, все, что осталось сделать, это один раз вызвать игровой цикл нашего Snake, чтобы начать игру. Это дает нам следующий полный код знаменитой игры Snake, созданный с использованием Canvas API и адской веб-пары HTML5/JavaScript:

Наша игра-змейка в действии

Наша Змея готова, пришло время протестировать ее в веб-браузере, чтобы увидеть, работает ли магия Змеи снова, как это было, когда Nokia возмутительно доминировала в мобильном мире:



Из этой игры «Змейка» вы можете представить себе несколько возможных улучшений. Например, вы можете добавить звук каждый раз, когда змея ест яблоко. Вы можете использовать API веб-хранилища HTML5 для хранения локального рекорда игрока. Таким образом, когда игрок побьет свой рекорд, вы сможете отобразить поздравительное сообщение. Возможности безграничны, и ваш единственный предел, как всегда в программировании, — это ваше воображение.


Посмотрите этот урок на YouTube

Это руководство также можно посмотреть на YouTube на канале SSaurel:


Также опубликовано здесь .