Автор оригинала: FreeCodeCamp Community Member.
В этой статье я собираюсь показать вам, как построить змею игру с JavaScript.
Игра змеи – это простая игра, в которой змея движется вокруг коробки, пытаясь съесть яблоко. Как только он успешно ест яблоко, длина змеи увеличивается, и движение становится быстрее.
Тогда игра окончена, когда змея бежит в себе или любая из четырех стен коробки.
Хорошо, давайте начнем с HTML и CSS (скелет для нашей игры).
HTML
Nokia 3310 snake
HTML выше довольно простой.
- У нас есть дерьма класса
Scoredisplay
Это будет отображать наши оценки. - Там дерьма класса
Сетка
Это будет размещать игру (это будет 10 на 10 сетки) - Класс
кнопка
В основном содержит кнопку для пользователей, играющих в игру на телефоне (мы автоматизируем его с клавиатурой для пользователя настольного компьютера). - И
всплывающее окно
Класс будет держать нашу кнопку воспроизведения.
Теперь давайте добавим немного стиля с CSS.
CSS.
body { background: rgb(212, 211, 211); } .grid { width: 200px; height: 200px; border: 1px solid red; margin: 0 auto; display: flex; flex-wrap: wrap; } .grid div { width: 20px; height: 20px; /*border:1px black solid; box-sizing:border-box*/ } .snake { background: blue; } .apple { background: yellow; border-radius: 20px; } .popup { background: rgb(32, 31, 31); width: 100px; height: 100px; position: fixed; top: 100px; left: 100px; display: flex; justify-content: center; align-items: center; }
В CSS, Сетка
Какой Gameboard имеет множество измерений и отображение Flex
Отказ Это позволяет содержимому (Div) этой сетке выстроиться в горизонтальную способ, как если бы они были встроены элементы вместо обычного блока, который они обладают.
Flex Wrap
Собственность просто перемещает Divs на следующую строку, предотвращая их прохождение на множество измерений их родительского элемента (сетка).
Мы будем динамически создавать содержимое игрового платы от JS, но мы можем придать ширину и высоту здесь (с .Grid
div). Я включил комментарии здесь, чтобы помочь вам на самом деле увидеть Divs, так как время продолжается, мы будем воспоминать код.
змея
и Яблоко
Классы должны показать нам, где змея и бонус в игре, а всплывающее окно
Класс – это фиксированный диван, который составляет воспроизвести
девочка
На данный момент вы должны иметь что-то подобное:
Теперь мы готовы к JavaScript.
Javascript
Первое, что нам нужно сделать, это определить ваши переменные:
let grid = document.querySelector(".grid"); let popup = document.querySelector(".popup"); let playAgain = document.querySelector(".playAgain"); let scoreDisplay = document.querySelector(".scoreDisplay"); let left = document.querySelector(".left"); let bottom = document.querySelector(".bottom"); let right = document.querySelector(".right"); let up = document.querySelector(".top"); let width = 10; let currentIndex = 0; let appleIndex = 0; let currentSnake = [2, 1, 0]; let direction = 1; let score = 0; let speed = 0.8; let intervalTime = 0; let interval = 0;
Переменная ширина именно то, что она есть (ширина сетки, то есть 10). Другие переменные будут иметь больше смысла, когда мы продолжаем – но поверьте, или не наша змея на самом деле на самом деле под названием Currentsnake
Отказ
Теперь давайте начнем с функций:
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("keyup", control); createBoard(); startGame(); playAgain.addEventListener("click", replay); });
Есть EventListener
На объекте документа под названием DomcontentLoaded
И это событие уволено сразу после загруженного содержимого HTML на нашем экране.
Как только это произойдет, мы устанавливаем EventListener в документ, чтобы посмотреть на щелчков на клавиатуре (больше на это позже). После этого мы хотим создать Gameboard
Запустите игру и следите за нажатиями на нашу кнопку воспроизведения.
Функция Preatboard
function createBoard() { popup.style.display = "none"; for (let i = 0; i < 100; i++) { let div = document.createElement("div"); grid.appendChild(div); } }
Как я уже сказал ранее, это 10 на 10 сетку, то есть нам понадобится 100 дев. Итак, сверху, мы закрываем всплывающее окно DIV, и мы верим до 100 каждый раз, когда мы создаем новый Div и добавить его в сетку (Gameboard).
Это сразу добавит некоторые из укладки, которые мы создали сверху (. График ДИД). Вы можете воврементировать стили CSS, и вы увидите созданные дивы (растресментировать их).
Функция startgame.
function startGame() { let squares = document.querySelectorAll(".grid div"); randomApple(squares); //random apple direction = 1; scoreDisplay.innerHTML = score; intervalTime = 1000; currentSnake = [2, 1, 0]; currentIndex = 0; currentSnake.forEach((index) => squares[index].classList.add("snake")); interval = setInterval(moveOutcome, intervalTime); }
startgame
Функция сначала получает все Divs (поскольку мы создаем Divs во время выполнения, мы не можем получить их в верхней части кода).
Далее мы выбираем место для нашего Apple. Мы сделаем это ниже в RandomApple
функция. направление
Относится к тому, где возглавляет змея – 1 справа, -1 для слева и так далее.
Интервал времени
Устанавливает время, необходимое для змеи, чтобы двигаться, а Currentsnake
Определяет, где именно на сетке змея будет (обратите внимание, что змея в основном пару Divs, учитывая определенный тип цвета).
Чтобы отобразить нашу змею на экране, мы будем петлю на Currentsnake
с foreach
Отказ С каждым значением мы получаем, мы будем использовать его с квадраты Отказ Помните, что мы получили доступ к решению решетки с QuerySelectorAll
Затем мы можем получить доступ к ним, как массив, который использует цифры. В нашем случае это значения Currentsnake
Отказ
После этого мы просто добавим Setinterval
Звоните (с функцией Move результат
и время Интервал
, который мы устанавливаем выше) к переменной Интервал
Отказ Это так, чтобы мы могли легко позвонить ClearInterval
на этой переменной.
RevetOwscece
Запускается каждые 1000 мс (1с) и в основном определяет, что происходит, когда вы перемещаете змею.
Функция AdomeOutsce.
function moveOutcome() { let squares = document.querySelectorAll(".grid div"); if (checkForHits(squares)) { alert("you hit something"); popup.style.display = "flex"; return clearInterval(interval); } else { moveSnake(squares); } }
Так нравится startgame
Функция выше, мы сначала получаем все Сетка
Divs, а затем мы проверяем, если CheckforHits
Функция возвращает true.
Если это так, это означает, что мы что-то ударили, а затем отображают кнопку воспроизведения, и она очищает интервал. Если он возвращает false, это означает, что мы ничего не ударили, и мы перемещаем змею с Movesnake
функция.
Так что в основном, каждая 1 секунды игра либо заканчивается, если CheckforHits
верно или мы перемещаем змею шагом вперед, если CheckforHits
неверно Я расскажу о Movesnake
Функция сначала.
Функция Movesnake
function moveSnake(squares) { let tail = currentSnake.pop(); squares[tail].classList.remove("snake"); currentSnake.unshift(currentSnake[0] + direction); // movement ends here eatApple(squares, tail); squares[currentSnake[0]].classList.add("snake"); }
Movesnake
Функция получает аргумент под названием квадраты
так что нам не нужно получить . Грид ДИВ снова в этой функции.
Первое, что нам нужно сделать, это удалить последний элемент Currentsnake
Массив через POP (это хвост, а первый элемент всегда головной). В основном змея поднимает шаг вперед, оставляя предыдущую позицию. После этого мы просто добавляем новое значение в начало массива с Неприносимость
Отказ
Предположим, что наша змея только начала двигаться и направлена на право (то есть). Это направление будет добавлено к Currentsnake
голова и сумма будет толкаться как новый Snakehead
Отказ
Например, если змея была в положении [2,1,0] Мы убираем последний элемент, оставив его в положении [2,1]. Тогда мы возьмем голову, которая есть 2 и добавить направление, которое является 1 и сделать это значение новое значение [3,2,1] который перемещает нашу змею шагом вперед вправо после одной секунды.
Если мы хотим переместить змею вниз, направление будет установлено на ширину (что 10) и добавлено к первому элементу (то есть 12 и нажато) [12,2,1] Отказ
После этого мы просто проверяем, ели ли змея яблоко и отображают новую змею на доме.
Функция CheckForHits
function checkForHits(squares) { if ( (currentSnake[0] + width >= width * width && direction === width) || (currentSnake[0] % width === width - 1 && direction === 1) || (currentSnake[0] % width === 0 && direction === -1) || (currentSnake[0] - width <= 0 && direction === -width) || squares[currentSnake[0] + direction].classList.contains("snake") ) { return true; } else { return false; } }
CheckforHits
Функция имеет заявление, если. В зависимости от определенного состояния он может либо вернуть истину (означающее, что мы что-то ударили) или ложь.
Первое условие – если Currentsnake
[0] (Глава змеи) + ширина (10) равна общей области ширины (то есть) и направление равно ширине.
Таким образом, в основном давайте предположим, что голова змеи находится в положении 97, который является последним слоем нашей сетки. Если бы вы добавили 10-97), то это больше, чем вся сетка, которая составляет 100. Если направление змеи все еще направляется вниз, то змея ударила нижнюю границу.
Если змея была в 97 году, но игрок смог изменить направление, скажем, 1 (например, они нажали левую клавишу), то это не ударило бы ничего.
Или ( ) Если остаток, когда глава змеи делится на ширину = Ширина-1 (например, 9) и направление 1 Отказ Каждый последний Div на правой стороне имеет значение 9, 19, 29
Если глава нашей змеи находится в положении 39, и направление по-прежнему 1 (то есть змея все еще движется к стене), то она попала что-то (правая стена).
Каждое другое условие в значительной степени противоположно наоборот двух выше. Конечное состояние позволяет, если глава змеи направляется в место, которое уже содержит классную змею, которая просто означает, что змея кусает себя.
Итак … Если какое-либо из условий выше, верно, змея что-то ударила и правда будет возвращен (else false). И если это так, игра окончена. Но если это ложно, переместите змею шагом вперед с Movesnake
Отказ
Функция Eytapple.
function eatApple(squares, tail) { if (squares[currentSnake[0]].classList.contains("apple")) { squares[currentSnake[0]].classList.remove("apple"); squares[tail].classList.add("snake"); currentSnake.push(tail); randomApple(squares); score++; scoreDisplay.textContent = score; clearInterval(interval); intervalTime = intervalTime * speed; interval = setInterval(moveOutcome, intervalTime); } }
Этапл
Функция называется из Movesnake
Функция каждый раз, когда змея поднимает шаг.
Получает два квадрата аргумента, . Грид ДИВ и хвост (в основном значение, которое было выпущено от змеи в overyoutsce WorkeOuts
). Затем он проверяет, следует ли перемещать следующую позицию нашу змею, содержит Apple.
Если это так, он просто добавляет этот хвост, мы вернулись к массиву. Это потому, что каждый раз, когда наша змея ест яблоко, которое мы хотим увеличить длину змеи одним значением – и что лучше, чем добавить хвост, который был выключен, когда он переместился?
Тогда мы просто выбираем новую позицию для нашего Apple с RandomApple
(см. ниже). После этого мы добавляем значение один На наш счет и показать его пользователю, очистить TimeInterval
(Чтобы мы могли увеличить скорость змеи, то есть время каждое движение происходит), а затем мы просто устанавливаем интервал обратно.
Функция RandomApple
function randomApple(squares) { do { appleIndex = Math.floor(Math.random() * squares.length); } while (squares[appleIndex].classList.contains("snake")); squares[appleIndex].classList.add("apple"); }
RandomApple
Просто выбирает место, чтобы разместить наше Apple, используя сделать пока петля. Сначала он выбирает случайную позицию с Math.random ()
В петле DO и проверяет, он выбрал ли он, содержит класс змеи.
Это означает, что условие в заявлении о работе будет продолжаться, пока не найдет пятно, которое не содержит змеи (продолжать делать это, пока это верно). Как только он найдет место, что просто дает это точку класса Apple.
Настройте элементы управления
Теперь нам нужно настроить наши элементы управления. Мы начнем с пользователей клавиатуры.
function control(e) { if (e.keycode === 39) { direction = 1; // right } else if (e.keycode === 38) { direction = -width; //if we press the up arrow, the snake will go ten divs up } else if (e.keycode === 37) { direction = -1; // left, the snake will go left one div } else if (e.keycode === 40) { direction = +width; // down the snake head will instantly appear 10 divs below from the current div } }
Помните сверху мы установили EventListener
для keyup Отказ Эта функция срабатывает сразу после ваших ручных нажимов и. Оставляет ключ на клавиатуре.
Теперь каждая кнопка на клавиатуре имеет значение под названием KeyCode (номера), к которым мы имеем доступ и сообщите нам, какой номер нажал. В основном мы будем наблюдать за клавишами со стрелками со своими соответствующими ключевыми кодами. С этим мы вносим изменения в направлении, например -1, 10 и так далее.
Хорошо, я надеюсь, что вы понимаете, как мы можем переместить змею сейчас.
Далее этот набор кнопок предназначен для мобильных устройств, и мы в основном делаем то же самое:
up.addEventListener("click", () => (direction = -width)); bottom.addEventListener("click", () => (direction = +width)); left.addEventListener("click", () => (direction = -1)); right.addEventListener("click", () => (direction = 1));
Последняя вещь, которую нам нужно сделать, это создать воспроизвести
Div Что будет всплыть, когда змея что-то попадет. Кнопка помогает нам сбросить игру.
Функция воспроизведения
function replay() { grid.innerHTML = ""; createBoard(); startGame(); popup.style.display = "none"; }
Сверху мы в основном ясно очищают сетку (Gameboard) и запустите предыдущие функции.
Поздравляю – вы добрались до конца! Вот окончательный результат:
Я надеюсь, что вы смогли кодировать и вам понравилось.
В этом уроке мы узнали, как создать нашу собственную змею игру с JavaScript. Некоторые другие важные концепции, которые мы покрыли, включают push, pop, setinterval, clearinterval и EventListener Отказ
Вы можете проверить финальную игру здесь: https://codepen.io/fako29/pen/dypxzg Отказ
Спасибо за чтение. Следуй за мной в Twitter здесь: https://twitter.com/fakorededami.