Progress-servis55.ru

Новости из мира ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Как создать игру на javascript

Создаем многопользовательскую веб-игру Javascript

Создаем многопользовательскую веб-игру Javascript

Вышедшая в 2015 году Agar.io стала прародителем нового жанра игр .io, популярность которого с тех пор сильно возросла. Рост популярности игр .io я испытал на себе: за последние три года я создал и продал две игры этого жанра..

На случай, если вы никогда раньше не слышали о таких играх: это бесплатные многопользовательские веб-игры, в которых легко участвовать (не требуется учётная запись). Обычно они сталкивают на одной арене множество противоборствующих игроков. Другие знаменитые игры жанра .io: Slither.io и Diep.io.

В этом посте мы будем разбираться, как с нуля создать игру .io. Для этого достаточно будет только знания Javascript: вам нужно понимать такие вещи, как синтаксис ES6, ключевое слово this и Promises. Даже если вы знаете Javascript не в совершенстве, то всё равно сможете разобраться в большей части поста.

Пример игры .io

Для помощи в обучении мы будем ссылаться на пример игры .io. Попробуйте в сыграть в неё!

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

1. Краткий обзор/структура проекта

В примере используется следующее:

  • Express — самый популярный веб-фреймворк для Node.js, управляющий веб-сервером игры.
  • socket.io — библиотека websocket для обмена данными между браузером и сервером.
  • Webpack — менеджер модулей. О том, зачем использовать Webpack, можно прочитать здесь.

Вот как выглядит структура каталога проекта:

public/

Всё в папке public/ будет статически передаваться сервером. В public/assets/ содержатся используемые нашим проектом изображения.

Весь исходный код находится в папке src/ . Названия client/ и server/ говорят сами за себя, а shared/ содержит файл констант, импортируемый и клиентом, и сервером.

2. Сборки/параметры проекта

Как сказано выше, для сборки проекта мы используем менеджер модулей Webpack. Давайте взглянем на нашу конфигурацию Webpack:

webpack.common.js:

Самыми важными здесь являются следующие строки:

  • src/client/index.js — это входная точка клиента Javascript (JS). Webpack будет начинать отсюда и станет рекурсивно искать другие импортированные файлы.
  • Выходной JS нашей сборки Webpack будет располагаться в каталоге dist/ . Я буду называть этот файл нашим пакетом JS.
  • Мы используем Babel, и в частности конфигурацию @babel/preset-env для транспиляции (transpiling) нашего кода JS для старых браузеров.
  • Мы используем плагин для извлечения всех CSS, на которые ссылаются файлы JS, и для объединения их в одном месте. Я буду называть его нашим пакетом CSS.

Вы могли заметить странные имена файлов пакетов ‘[name].[contenthash].ext’ . В них содержатся подстановки имён файлов Webpack: [name] будет заменён на имя входной точки (в нашем случае это game ), а [contenthash] будет заменён на хеш содержимого файла. Мы делаем это, чтобы оптимизировать проект для хеширования — можно приказать браузерам бесконечно кешировать наши пакеты JS, потому что если пакет изменяется, то меняется и его имя файла (изменяется contenthash ). Готовым результатом будет имя файла вида game.dbeee76e91a97d0c7207.js .

Читать еще:  Интерфейс cloneable java

Файл webpack.common.js — это базовый файл конфигурации, который мы импортируем в конфигурации разработки и готового проекта. Вот, например, конфигурация разработки:

webpack.dev.js

Для эффективности мы используем в процессе разработки webpack.dev.js , и переключается на webpack.prod.js , чтобы оптимизировать размеры пакетов при развёртывании в продакшен.

Локальная настройка

Рекомендую устанавливать проект на локальной машине, чтобы вы могли следовать за этапами, перечисленными в этом посте. Настройка проста: во-первых, в системе должны быть установлены Node и NPM. Далее нужно выполнить

и вы готовы к работе! Для запуска сервера разработки достаточно выполнить

и зайти в веб-браузере на localhost:3000. Сервер разработки будет автоматически пересобирать заново пакеты JS и CSS в процессе изменения кода — просто обновите страницу, чтобы увидеть все изменения!

3. Входные точки клиента

Давайте приступим к самому коду игры. Для начала нам потребуется страница index.html , при посещении сайта браузер будет загружать её первой. Наша страница будет довольно простой:

index.html

Этот пример кода слегка упрощён для понятности, то же самое я сделаю и со многими другими примерами поста. Полный код всегда можно посмотреть на Github.

  • Элемент HTML5 Canvas ( ), который мы будем использовать для рендеринга игры.
  • для добавления нашего пакета CSS.

Создаём простую игру на Vanilla JS

  • Переводы, 4 октября 2018 в 11:52
  • Никита Прияцелюк

В этой статье мы создадим простую игру с помощью HTML5, CSS3 и чистого JavaScript. Вам не понадобятся глубокие знания программирования. Если вы знаете, для чего нужны HTML, CSS и JS, то этого более чем достаточно. На работу игры вы можете посмотреть здесь.

Структура файлов

Начнём с создания нужных папок и файлов:

Начальный шаблон, соединяющий CSS- и JS-файлы:

В игре будет 12 карточек. Каждая карта состоит из контейнера div с классом .memory-card , внутри которого находится два элемента img . Первая отвечает за лицо ( front-face ) карточки, а вторая — за рубашку ( back-face ).

Необходимые изображения можно скачать из репозитория проекта.

Обернём набор карточек в контейнер section . В итоге получаем:

Мы используем простой, но очень полезный сброс стилей, который будет применён ко всем элементам:

Свойство box-sizing: border-box учитывает значения внутренних отступов и границ элемента при подсчёте общей высоты и ширины, поэтому нам не нужно заниматься математикой.

Если применить к body свойство display: flex и margin: auto к контейнеру .memory-game , то он будет выровнен вертикально и горизонтально.

.memory-game также будет flex-контейнером. По умолчанию ширина элементов уменьшается, чтобы они помещались в контейнер. Если присвоить свойству flex-wrap значение wrap , элементы будут располагаться на нескольких строках в соответствии с их размерами:

Ширина и высота каждой карточки подсчитывается с помощью CSS-функции calc() . Создадим три ряда по четыре карточки, установив значения ширины и высоты равными 25% и 33.333% соответственно минус 10px от внешнего отступа.

LATOKEN, Москва, от 4000 до 5000 $

Чтобы разместить наследников .memory-card , добавим position: relative . Так мы сможем абсолютно расположить наследников относительно родительского элемента.

Свойство position: absolute , установленное для .front-face и .back-face , уберёт элементы с их исходных позиций и разместит поверх друг друга:

Поле из карточек должно выглядеть примерно так:

Добавим ещё эффект при клике. Псевдокласс :active будет срабатывать при каждом нажатии на элемент. Он устанавливает длительность анимации равной 0.2 с:

Переворачиваем карточки

Чтобы перевернуть карточку после нажатия, добавим класс flip . Для этого давайте выберем все элементы memory-card с помощью document.querySelectorAll() . Затем пройдёмся по ним в forEach -цикле и добавим обработчики событий. При каждом нажатии на карточку будет вызываться функция flipCard() . this отвечает за нажатую карточку. Функция получает доступ к списку классов элемента и активирует класс flip :

CSS класс flip переворачивает карточку на 180 градусов:

Чтобы создать 3D-эффект переворота, добавим свойство perspective в .memory-game . Это свойство отвечает за расстояние между объектом и пользователем в z-плоскости. Чем ниже значение, тем сильнее эффект. Установим значение 1000px для едва уловимого эффекта:

Добавим к элементам .memory-card свойство transform-style: preserve-3d , чтобы поместить их в 3D-пространство, созданное в родителе, вместо того, чтобы ограничивать их плоскостью z = 0 (transform-style):

Теперь мы можем применить transition к свойству transform , чтобы создать эффект движения:

Отлично, теперь карточки переворачиваются в 3D! Но почему мы не видим лицо карточки? На данный момент .front-face и .back-face наложены друг на друга из-за абсолютного позиционирования. Рубашкой каждого элемента является зеркальное отражение его лица. По умолчанию значение свойства backface-visibility равно visible , поэтому вот что мы видим при перевороте карточки:

Чтобы исправить это, применим свойство backface-visibility: hidden для .front-face и .back-face :

Если перезагрузить страницу и снова перевернуть карточку, она пропадёт!

Так как мы скрыли заднюю сторону обеих картинок, на обратной стороне ничего нет. Поэтому сейчас нам нужно перевернуть .front-face на 180 градусов:

Наконец, мы получили желаемый эффект переворота!

Ищем пару

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

После нажатия на первую карточку она ожидает переворота другой. Переменные hasFlippedCard и flippedCard будут отвечать за состояние переворота. Если ни одна карточка не перевёрнута, значение hasFlippedCard устанавливается равным true , а нажатой карточке присваивается flippedCard . Ещё давайте сменим метод toggle() на add() :

Теперь при нажатии на вторую карточку мы попадаем в else-блок нашего условия. Чтобы проверить, совпадают ли карточки, нужно их всех идентифицировать.

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

Теперь мы можем проверить, совпадают ли карточки, с помощью свойства dataset . Поместим логику сравнения в метод checkForMatch() и снова присвоим переменной hasFlippedCard значение false . В случае совпадения будет вызван метод disableCards() и обработчики событий будут откреплены от обеих карточек, чтобы предотвратить их переворот. В противном случае метод unflipCards() перевернёт обе карточки с помощью 1500 мс тайм-аута, который удалит класс .flip :

Складываем всё воедино:

Более элегантный способ написать условие совпадения — тернарный оператор. Он состоит из трёх частей. Первая часть — это условие, вторая часть выполняется, если условие возвращает true , в противном случае выполняется третья часть:

Блокируем поле

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

Объявим переменную lockBoard . Когда игрок нажмёт на вторую карточку, lockBoard будет присвоено значение true , а условие if (lockBoard) return; предотвратит переворот других карточек до того, как эти две будут спрятаны или совпадут:

Нажатие на ту же карточку

У нас всё ещё есть сценарий, при котором после нажатия на одну карточку дважды условие совпадения будет выполнено и обработчик событий будет удалён.

Чтобы избежать этого, добавим проверку на то, равняется ли нажатая карточка переменной firstCard , и вёрнемся из функции, если это так:

Переменные firstCard и secondCard нужно обнулять после каждого раунда. Реализуем эту логику в новом методе resetBoard() . Поместим в него hasFlippedCard = false и lockBoard = false . Деструктурирующее присваивание [var1, var2] = [‘value1’, ‘value2’] из ES6 позволяет писать код меньших размеров:

Новый метод будет вызываться из disableCards() и unflipCards() :

Перемешивание

Наша игра выглядит довольно неплохо, но играть в неё не очень весело, если карточки всегда на одном месте. Пора это исправить.

Когда у контейнера есть свойство display: flex , его элементы упорядочиваются сначала по номеру группы, а потом по порядку в исходном коде. Каждая группа определяется свойством order , которое содержит положительное или отрицательное целое число. По умолчанию свойство order каждого flex-элемента имеет значение 0 . Если групп больше одной, элементы сначала упорядочиваются по возрастанию порядка группы.

В игре есть 12 карточек, поэтому мы пройдёмся по ним в цикле, сгенерируем случайное число от 0 до 12 и присвоим его свойству order :

Чтобы вызвать функцию shuffle() , сделаем её IIFE (Immediately Invoked Function Expression). Это значит, что она будет выполнена сразу после объявления. Скрипт должен иметь примерно такой вид:

Ссылка на основную публикацию
Adblock
detector