Canvas — cоздание простой игры
Данная статья планируется как пошаговый обзор создания простой JavaScript-игры класса “Ball and Paddle” на Canvas. Примерами такой игры могут послужить старые DOS-е игры наподобие таких — Ball and Paddle.
Пример кода из этой статьи взят из видео-курса достаточно известного Интернет-ресурса, посвященного фронтенд-разработке — Udemy.
Почему Canvas и почему игра? Лично для меня процесс познания JavaScript сильно облегчается благодаря Canvas — так интереснее. А создание игры на Canvas — это еще интереснее!
Итак, с чего начнем? Дальше в меру своих сил буду стараться детально пошагово рассказывать, что делает тот или иной кусок кода. И начнем с базового набора — создания Canvas.
Базовый Canvas
HTML-разметка страницы будет предельно простой:
В JavaScript’е создадим две глобальные переменные — одну для элемента Canvas, вторую — для 2d-контекста Canvas. Когда parser браузера построит DOM-дерево документа (событие ), инициализируем обе переменные, выполним проверку удачного получения 2d-контекста Canvas и если проверка будет пройдена успешно, то динамически зададим размеры Canvas:
Базовые элементы игры
Основа Canvas была создана в предыдущем шаге. В этом шаге создадим три фигуры, которые будут учавствовать в игре. Таковыми фигурами будут:
- фон игры
- мячик (ball)
- площадка (paddle)
Ниже я приведу JavaScript-код создания всех трех элементов, но сам код комментировать не буду, так как он очень простой и относится к основам Canvas:
Живой результат вышеприведенного кода можно посмотреть на этой странице — Lesson1-1. Это то, что должно получиться и что послужит заготовкой для игры.
Анимация мячика
В этом шаге предстоит сделать более интересные вещи. Во-первых, мы сделаем так, чтобы мячик начал двигаться как по-горизонтали, так и по-вертикали. А во-вторых, сделаем так, чтобы он вел себя как настоящий резиновый мячик — при ударе о стену отскакивал от нее и мчался в противоположном направлении.
Сделать это достаточно просто. Для этого нам понадобится одна из так называемых тайминговых функций JavaScript — . А также немного воображения.
Анимация мячика будем делать по-простому принципу, по которому делается любой мультфильм или кино — мячик будет отрисовываться с заданной частотой ( ), но каждый раз в новой позиции. В результате будет создаваться иллюзия его движения. Каждая новая позиция мячика — это его координата по оси X или Y с новым значением соответственно.
Чтобы мячик двигался достаточно быстро, изменять значения координат ( и ) мячика по оси X и Y будем с определенным шагом ( и ) — допустим, со значениями 5 или 6:
Эффект отскакивания от стенок (как резиновый мячик) обеспечивает проверка условий в участке кода:
Здесь все просто — при выполнении условия знак переменной или будет меняться на противоположный. В результате значение переменной или будет возрастать или уменьшаться. Как следствие, мячик будет двигаться в одну или в другую сторону.
Живой пример приведенного выше кода можно посмотреть и изучить на этой странице — Lesson1-2.
Двигаем paddle
В этом шаге нужно заставить двигаться paddle при помощи мыши. Для этого по событию внутри элемента Canvas будем получать значение X-координаты курсора мыши. И передавать это значение элементу paddle, его X-координате левого верхнего угла. Тем самым мы заставим paddle двигаться. За все эти действия будет отвечать функция :
Обратите внимание на последнюю строку функции — . Переменная необходима для того, чтобы при выходе за границы Canvas элемент paddle скрывался ровно на половину своей ширины.
Также не забудем создать переменные для paddle и передать их в код для отрисовки фигуры:
Живой пример приведенного выше кода можно посмотреть и изучить на этой странице — Lesson1-3. Подвигайте курсором мыши право-влево, чтобы увидеть эффект.
Мячик отскакивает от paddle
На этом этапе нужно сделать так, чтобы мячик отскакивал от paddle, когда последний оказывается на его пути. Выполнить эту задачу просто — ведь мячик уже отскакивает от “стен” Canvas. Следовательно, нужно научить мячик “видеть” еще и paddle.
Для этого сначала нужно опеределить внешние границы paddle — все его четыре стороны:
Когда значения всех сторон будут определены, то можно будет подставить эти значения в условие — и дело сделано:
Живой пример приведенного выше кода можно посмотреть и изучить на этой странице — Lesson1-4. Подвигайте курсором мыши право-влево и постарайтесь поймать мячик с помощью paddle, чтобы увидеть эффект.
Угол отскока мячика
В этом шаге сделаем так, чтобы наша игра смотрелась более правильной с точки зрения физики и обычной природы. То есть, при разном угле попадания на paddle мячик должен отскакивать от него с разной скоростью. Чем острее угол падения, тем с большей скоростью отскакивает от paddle мячик.
Решается эта задача несколькими строками кода:
В первой строке находится X-координата середины paddle. В строке определяется расстояние, на котором мячик соприкоснулся с paddle относительно его середины. В строке полученная дистанция присваивается шагу приращения по оси Х мячика — .
Логично предположить, что чем больше величина дистанции точки соприкосновения мячика относительно середины paddle, тем выше новая скорость движения мячика по-горизонтали. Чтобы эта скорость не была слишком высокой, ее необходимо уменьшить, умножив на 0.35, к примеру.
Живой пример приведенного выше кода можно посмотреть и изучить на этой странице — Lesson1-5.
Оптимизация кода
На данный момент наша задача по построению игры практически решена. Но остался один организационный момент.
Заключается он в том, что код необходимо реорганизовать в отдельные функции. Такой код будет читаться и поддерживаться значительно лучше.
Одна из таких функций уже была создана ранее — это функция . Давайте преобразуемся и весь оставшийся код подобным образом:
Готовый пример преобразованного в функции кода можно посмотреть на этой странице — Lesson1-6.
Красивая функция trackBy
Пример красивой функции trackBy для Angular. Функция понравилась своей лаконичностью:<% highlight typescript %>public trackByNumber = (_. … Continue reading
Пошаговый алгоритм разработки браузерных игр
Браузерные игры — это компьютерные игры, которые можно запускать или воспроизводить через веб-браузер. Они созданы с использованием таких технологий, как HTML, JavaScript и Adobe Flash. Эти игры обычно разрабатываются таким образом, чтобы предложить пользователям короткий, увлекательный опыт. Существует множество различных типов браузерных игр, начиная от ролевых онлайн-игр и заканчивая простыми головоломками. Они, как правило, просты в игре и предлагают игрокам возможность посоревноваться друг с другом за награды или за высокий балл.
Типы браузерных игр
Самым популярным видом браузерных игр является ролевая онлайн-игра. Эти игры часто включают в себя создание персонажа, выполнение заданий и взаимодействие с другими игроками. Игроки также могут набирать очки опыта и развивать своего персонажа по мере прохождения игры. Другие типы браузерных игр включают карточные игры, стратегические игры и головоломки.
Особенности браузерных игр
Браузерные игры, как правило, ориентированы на легкий доступ и, как правило, короткое время игры. Как правило, они разработаны таким образом, чтобы быть простыми и понятными. Таким образом, графика и звук часто довольно просты, но в некоторых играх используются новейшие технологии для создания ярких миров. Игровой процесс обычно быстро развивается, так как игроки постоянно соревнуются друг с другом за то, чтобы набрать наибольшее количество очков или занять позицию в таблице лидеров.
Преимущества браузерных игр
- В браузерные игры обычно легко играть
- К ним быстро и легко получить доступ
- Как правило, они предлагают веселый и увлекательный опыт
- Игроки могут соревноваться друг с другом за награды или высокие баллы
- Игроки могут развивать своего персонажа по мере прохождения игры
Что такое алгоритм?
Что такое алгоритм?
Алгоритм — это набор инструкций, или шагов, которые выполняются для решения задачи. Алгоритмы используются в вычислениях, обработке данных и автоматизированном рассуждении. Они могут быть сведены к серии упорядоченных инструкций, обычно представленных математическими символами или логическими соотношениями.
Идея алгоритма существует с незапамятных времен. Древние греки, вавилоняне и египтяне использовали алгоритмы для решения различных математических и физических задач. Позже индийские и китайские математики разработали алгоритмы для записи астрономических наблюдений и вычислений, таких как извлечение квадратных и кубических корней.
Современные компьютерные алгоритмы можно разделить на две большие категории: алгоритмы для решения задач и алгоритмы для решения задач в реальном времени. Алгоритмы решения задач помогают найти решения конкретной проблемы. Примеры алгоритмов для решения задач включают алгоритмы сортировки, поиска и оптимизации. Алгоритмы решения задач помогают выполнить конкретную задачу. Примерами алгоритмов для решения задач являются алгоритмы машинного обучения, графические алгоритмы и нейронные сети.
Типы алгоритмов
- Алгоритмы сортировки: Алгоритмы сортировки используются для упорядочивания элементов данных в определенном порядке, часто в порядке возрастания или убывания. Распространенные алгоритмы сортировки включают пузырьковую сортировку, сортировку по вставке, сортировку по выбору, быструю сортировку и сортировку слиянием.
- Алгоритмы поиска: Алгоритмы поиска используются для поиска определенных элементов в структуре данных, таких как массив или связанный список. Они часто основаны на сравнениях между элементами в структуре данных. Распространенные алгоритмы поиска включают линейный поиск, бинарный поиск и поиск по глубине.
- Алгоритмы оптимизации: Алгоритмы оптимизации используются для повышения эффективности и быстродействия системы. Распространенные алгоритмы оптимизации включают в себя восхождение на холм, имитацию отжига и генетические алгоритмы.
- Алгоритмы машинного обучения: Алгоритмы машинного обучения используются для построения прогностических моделей, которые могут принимать решения или прогнозы без специальных инструкций. Распространенные алгоритмы машинного обучения включают деревья решений, машины опорных векторов (SVM) и нейронные сети.
- Графические алгоритмы: Графические алгоритмы используются для решения задач, связанных с графами, таких как поиск кратчайшего пути между двумя узлами на графе. Распространенные графические алгоритмы включают BFS, DFS и A*.
- Нейронные сети: Нейронные сети используются для моделирования поведения биологических нейронов. Они могут выявлять закономерности, принимать решения и делать прогнозы на основе своих обучающих данных.
Алгоритм является неотъемлемой частью вычислений и автоматизированного мышления. С развитием современных компьютерных систем алгоритмы приобрели еще большее значение, поскольку теперь они используются для решения сложных проблем и задач, которые раньше было бы невозможно решить.
Веб-технологии для разработки игр
| Веб-технологии | Описание | Преимущества |
|---|---|---|
| HTML5 | HTML5 — это пятая основная версия стандарта HTML для структурирования и представления контента в Интернете. | HTML5 не зависит от устройства, поддерживает мультимедиа, такие как аудио и видео, и поддерживает несколько браузеров. Он также поддерживает автономный доступ и хранение. |
| Three.js | Three.js представляет собой кроссбраузерную библиотеку JavaScript и интерфейс прикладного программирования, используемый для создания и отображения анимированной 3D компьютерной графики в веб-браузере. | Three.js обеспечивает поддержку световых карт, теней, шейдерных эффектов и эффектов постобработки. Он основан на WebGL, что позволяет использовать его на любом устройстве, поддерживающем браузер. |
| WebGL | WebGL — это JavaScript API, используемый для рендеринга интерактивной компьютерной 3D-графики и 2D-графики в любом совместимом веб-браузере. | WebGL позволяет использовать 3D-графику с аппаратным ускорением в браузере без помощи подключаемых модулей. Это помогает в значительной степени сократить время разработки и стоимость разработки игр. |
Настройка логической структуры игры

Настройка логической структуры игры
При разработке игры важно на ранней стадии определить ее логическую структуру. Это повлияет на то, как будет развиваться остальная часть игры, позволяя вам опираться на прочный фундамент. Чтобы создать логическую структуру игры, необходимо предпринять несколько шагов:
Определите концепцию и цели игры.
Первым шагом к созданию игры является определение основных концепций и целей, которые в конечном счете придают целенаправленность действиям игрока. Это включает в себя основную тему, цель, структуру сюжета и задачи игры.
Разрабатывайте игровую механику.
Используя игровые концепции и цели, разработайте игровую механику. Это включает в себя правила, элементы управления игроком, интерактивные элементы и т.д., из которых состоит игра.
Разработка уровней, пожалуй, является самым важным шагом в создании логической структуры игры, поскольку она определяет, как будет развиваться игра. К проектированию уровней можно применить множество различных подходов, таких как использование линейной прогрессии, нелинейной прогрессии или некоторой комбинации этих двух методов.
Объедините художественное оформление и аудио.
Наконец, интегрируйте графику и аудио в игру. Графика и аудио могут придать игре особый внешний вид и сделать ее более привлекательной для игроков.
Следуя этим шагам, логическую структуру игры можно создать комплексным образом, что даст игре прочную основу для построения остальной части игры.
Разработка пользовательского интерфейса
Разработка пользовательского интерфейса
Дизайн пользовательского интерфейса (UI) — это процесс разработки визуальных элементов цифрового продукта с учетом интересов конечного пользователя. Этот процесс помогает создать более простой и приятный интерфейс для пользователя. Дизайн пользовательского интерфейса охватывает все аспекты взаимодействия с пользователем — от выбора шрифтов, цветовых схем и визуальных элементов до системной логики, программирования и навигации.
Элементы дизайна
Элементы дизайна — это строительные блоки дизайна пользовательского интерфейса. Эти элементы используются для создания общего внешнего вида цифрового продукта и расположены таким образом, чтобы сформировать визуальную иерархию. Как правило, они предназначены для того, чтобы сделать пользовательский интерфейс интуитивно понятным и простым в навигации.
- Цвет: Цвет важен для любого дизайна пользовательского интерфейса. Цвета создают эмоции, привлекают внимание пользователя и помогают донести информацию. Эффективное использование цвета может помочь пользователям легко идентифицировать элементы на странице.
- Типографика: Типографика относится к стилю и размеру текста, используемого в пользовательском интерфейсе. Важно выбрать подходящий размер шрифта, который был бы разборчивым и хорошо видимым на всех устройствах. Стиль шрифта также должен соответствовать общему внешнему виду продукта.
- Значки: Значки — это визуальные символы, используемые для представления действий или элементов в пользовательском интерфейсе. Значки должны быть спроектированы таким образом, чтобы быть легко узнаваемыми и понятными, чтобы они быстро сообщали о своем назначении.
- Элементы пользовательского интерфейса: элементы пользовательского интерфейса — это объекты, составляющие пользовательский интерфейс. Навигационные инструменты, такие как меню, кнопки и выпадающие списки, — все это примеры элементов пользовательского интерфейса.
- Макет: Макет пользовательского интерфейса влияет на то, как пользователи взаимодействуют с ним. Важно расположить элементы дизайна таким образом, чтобы пользователь мог легко найти нужную ему информацию.
Тестирование юзабилити
Юзабилити-тестирование — важная часть дизайна пользовательского интерфейса. Он используется для определения того, насколько успешно дизайн удовлетворяет потребностям и целям пользователей. Это включает в себя тестирование дизайна с пользователями, чтобы оценить простоту использования и способность решать проблемы пользователей. Этот процесс может помочь выявить любые потенциальные проблемы или области для улучшения дизайна.
Создание ресурсов для игры
| Создание ресурсов для игры |
|---|
| Создавайте персонажей и уровни |
| Создавайте художественные активы |
| Добавление звука в игру |
| Создание ресурсов для игры | Полезная информация |
|---|---|
| Создавайте персонажей и уровни | Игра должна быть разработана с учетом персонажей, принимая во внимание, как они будут визуально выглядеть и взаимодействовать на уровнях. |
| Создавайте художественные активы | Художественные материалы должны быть созданы в соответствии с тематикой игры. Такие ресурсы, как фон, текстуры и спрайты, должны дополнять общий вид игры. |
| Добавление звука в игру | Добавление звуковых эффектов и фоновой музыки может помочь оживить игру и улучшить впечатления игрока. |
Программирование логики игры
Программирование логики игры
Создание игры требует написания кода для создания логики игры. Этот код использует алгоритмы и структуры, которые определяют, как работает игра. Именно программирование объединяет графику, звук и сюжеты, придавая игре ее ощущение, играбельность и уровень интереса.
Заставляем игру работать
Написание программного кода для игры включает в себя множество задач. Эти задачи включают в себя:
- Определение правил
- Написание кода для создания визуальных и звуковых элементов
- Тестирование логики игры на разных платформах
- Отладка проблем при их возникновении
Программирование логики игры имеет важное значение для правильного прохождения игры. Без этого в игру может быть неприятно играть или она может быть недостаточно воспроизводимой. Код должен быть написан с тщательным вниманием к деталям, чтобы создать надлежащий игровой процесс.
Инструменты для программирования игр
Разработчикам доступно множество инструментов для написания кода для программирования игр. К ним относятся популярные языки программирования, игровые движки и программные средства.
- Языки программирования включают C++, Java, C#, Python и HTML5
- Игровые движки, такие как Unity, Unreal Engine и Construct 3
- Программные инструменты, такие как GitHub, Visual Studio и Adobe Creative Cloud
Эти инструменты упрощают программирование игр, поскольку предоставляют полезные функции для упрощения работы.
Вывод
Написание программного кода для игры является важнейшим компонентом разработки игр. Важно использовать правильные инструменты и уделять пристальное внимание коду для достижения наилучшего результата в игре. Правильное программирование логики игры создает игру, в которую игрокам нравится играть.
Отладка и тестирование
.
Отладка и тестирование
Отладка и тестирование — это два важных, отличных друг от друга процесса в рамках жизненного цикла разработки программного обеспечения. Отладка — это процесс удаления ошибок из приложения, в то время как тестирование — это процесс, который используется для определения корректности, полноты и качества приложения.
Отладка
- Отладка — это процесс отладки C++ или любого другого типа программного обеспечения на языке программирования с целью выявления и исправления ошибок.
- Как правило, отладка выполняется вручную, с помощью отладчика. Отладчик — это программа, которую можно использовать для установки точек останова, проверки переменных и отслеживания инструкций.
- Во время отладки разработчики могут за один шаг просмотреть свой код и определить точное место, где произошла ошибка.
- Отладка обычно требует специальных технических знаний и навыков, поэтому обычно ею занимаются опытные разработчики или инженеры.
- Отладку следует выполнять независимо от размера проекта, даже если он небольшой.
Тестирование
- Тестирование — это процесс запуска приложения или системы с помощью набора тестов, чтобы определить, соответствует ли оно требованиям и работает ли должным образом.
- Тестирование может проводиться вручную или с помощью автоматизированных инструментов.
- Тестирование обычно проводится тестировщиками, которые обладают специализированными знаниями и навыками в области тестирования.
- Различные типы тестирования проводятся на различных этапах жизненного цикла разработки и используются для проверки функциональности и производительности приложения.
- Различные типы тестов включают модульное тестирование, интеграционное тестирование, приемочное тестирование, стресс-тестирование и тестирование пользовательского опыта.
Публикация игры
| Задача | Необходимая работа/Время | Требуемые навыки |
|---|---|---|
| Программирование | Требуются долгие часы и усилия | Хорошие навыки программирования, математики и решения проблем |
| Игровой дизайн | Месяцы или годы разработки | Творческий склад ума, понимание игровой механики |
| Маркетинг и реклама | Недели или месяцы воздействия | Стратегическое планирование, исследование рынка, анализ действий конкурентов |
Техническое обслуживание и непрерывная поддержка
Техническое обслуживание и непрерывная поддержка
Техническое обслуживание и непрерывная поддержка являются ключом к тому, чтобы ваше программное обеспечение и приложения оставались актуальными и работали эффективно. Это требует от вашей организации приверженности обеспечению регулярного обслуживания всех ИТ-систем. Это включает в себя такие вещи, как внесение исправлений, резервное копирование, управление данными и безопасность. Непрерывная поддержка — это услуга, которая предоставляется клиентам для обеспечения постоянной оптимальной работы их ИТ-систем. Этот вид услуг обычно включает в себя службу поддержки, которая доступна 24/7.
Что входит в техническое обслуживание и непрерывную поддержку?
- Обновления программного обеспечения: Обновление программного обеспечения с помощью последних исправлений и выпусков гарантирует, что ваши приложения будут безопасными и будут работать бесперебойно.
- Резервное копирование и управление данными: Наличие надежной системы резервного копирования гарантирует, что вы не потеряете никаких важных данных в случае аварии.
- Безопасность: Обеспечение безопасности ваших систем имеет важное значение для эффективного управления данными и защиты приложений. Это включает в себя такие вещи, как установка антивируса и другие меры безопасности.
- Служба поддержки: Непрерывная поддержка обычно включает в себя круглосуточную службу поддержки 7 дней в неделю, что позволяет пользователям получать помощь и советы всякий раз, когда они в этом нуждаются.
Преимущества технического обслуживания и непрерывной поддержки
- Надежность: Регулярное техническое обслуживание и непрерывная поддержка помогают обеспечить бесперебойную и эффективную работу ваших ИТ-систем в любое время.
- Безопасность: Регулярно поддерживая и исправляя свои ИТ-системы, вы можете помочь обеспечить безопасность ваших данных и приложений.
- Поддержка: Постоянная поддержка предоставляет специальную команду поддержки, которая поможет с любыми проблемами, которые могут возникнуть.
- Экономия средств: Регулярно обслуживая и исправляя свои ИТ-системы, вы можете сэкономить деньги, предотвратив дорогостоящий ремонт в будущем.
Основные вопросы по теме «gamedev»
Игровой дизайн
Определение целей игры, темы и правил; создание дизайна уровней; и выбор персонажа.
Программирование
Написание кода для игровой механики, реализация спецэффектов и исправление ошибок.
Тестирование
Выявление и решение технических проблем; проверка функций и контента игры.
Маркетинг
Продвижение игры, управление PR-кампаниями и выпуск регулярных обновлений.
Какие шаги мне нужно предпринять для разработки браузерной игры?
- Принятие решения о концепции игры и ее особенностях.
- Создание концепт-артов, таких как дизайн пользовательского интерфейса игры и дизайн персонажей / мира.
- Настройка игрового окружения.
- Разработка игровой логики с помощью подходящего языка программирования.
- Тестируем игру и вносим исправления.
- Развертывание игры на сервере и/или запуск ее в браузере.
Какой язык программирования я должен использовать для разработки браузерной игры?
Многие языки программирования, такие как JavaScript, HTML5, Unity и Flash, могут быть использованы для разработки браузерных игр. Какой язык вы выберете, будет зависеть от типа игры, которую вы разрабатываете.
Создаем многопользовательскую браузерную игру. Часть первая. Клиент-серверная архитектура
В 2014 году я впервые побывал на CodeDay в Нью-Йорке. И хотя CodeDay не совсем хакатон, это было моё первое знакомство с подобными мероприятиями. Там мы с моим другом Кеннетом Ли написали многопользовательскую игру в танчики. Так как несколько моих друзей спрашивали меня о том, как я её написал, я решил описать процесс её создания.
В этом посте я вкратце опишу ход своих рассуждений и покажу, как воссоздать архитектуру, а также дам некоторые советы, если вы захотите сделать игру сами. Этот пост рассчитан на тех, кто владеет основами JavaScript и Node.js. Если вы с ними не знакомы, то есть много замечательных онлайн-ресурсов, где можно их изучить.
Прим. перев. На нашем сайте есть много познавательных материалов как по JavaScript, так и по Node.js — обязательно найдёте что-нибудь подходящее.
Бэкенд игры написан на Node.js с использованием веб-сокетов, которые позволяют серверу и клиенту общаться в режиме реального времени. Со стороны клиента игра отображается в HTML5-элементе Canvas . Для начала нам, конечно же, понадобится Node.js. В этой статье описана работа с версией 6.3.1, но вы можете использовать любую версию выше 0.12.
Прим. перев. Если вы не знакомы с веб-сокетами, рекомендуем прочитать наш вводный материал.
Создание проекта
Для начала установите зависимости. Создайте папку проекта, перейдите в неё и запустите следующий код:
Для быстрой настройки сервера целесообразно использовать фреймворк Express, а для обработки веб-сокетов на сервере — пакет socket.io. В файл server.js поместите следующий код:
Это довольно типичный код для сервера на связке Node.js + Express. Он устанавливает зависимости и основные маршруты сервера. Для этого демонстрационного приложения используется только один файл index.html и папка static . Создайте их в корневой папке проекта. Файл index.html довольно простой:
Ваш пользовательский интерфейс может содержать куда больше элементов, поэтому для более крупных проектов CSS-стили лучше помещать в отдельный файл. Для простоты я оставлю CSS в коде HTML. Обратите внимание, что я включил в код скрипт socket.io.js . Он автоматически заработает в рамках пакета socket.io при запуске сервера.
Теперь нужно настроить веб-сокеты на сервере. В конец файла server.js добавьте:
Пока что в игре нет никаких функций, поэтому в обработчик веб-сокетов ничего добавлять не нужно. Для тестирования допишите следующие строки в конец файла server.js :
Эта функция будет отправлять сообщение с именем message и содержимым hi всем подключенным веб-сокетам. Позже не забудьте удалить эту часть кода, так как она предназначена только для тестирования.
В папке static создайте файл с именем game.js . Вы можете написать короткую функцию для регистрации сообщений от сервера, чтобы убедиться в том, что вы их получаете. В файле static/game.js пропишите следующее:
Запустите сервер командой node server.js и в любом браузере перейдите по ссылке http://localhost:5000. Если вы откроете окно разработчика (нажать правую кнопку мыши → Проверить (Inspect)), то увидите, как каждую секунду приходит новое сообщение:

Как правило, socket.emit(name, data) отправляет сообщение с заданным именем и данными серверу, если запрос идет от клиента, и наоборот, если запрос идет от сервера. Для получения сообщений по конкретному имени используется следующая команда:
С помощью socket.emit() вы можете отправить любое сообщение. Можно также передавать объекты JSON, что для нас очень удобно. Это позволяет мгновенно передавать информацию в игре от сервера к клиенту и обратно, что является основой многопользовательской игры.
Теперь пусть клиент отправляет некоторые состояния клавиатуры. Поместите следующий код в конец файла static/game.js :
Это стандартный код, который позволяет отслеживать нажатие клавиш W , A , S , D . После этого добавьте сообщение, которое оповестит сервер о том, что в игре появился новый участник, и создайте цикл, который будет сообщать серверу о нажатии клавиш.
Эта часть кода позволит отправлять на сервер информацию о состоянии клавиатуры клиента 60 раз в секунду. Теперь необходимо прописать эту ситуацию со стороны сервера. В конец файла server.js добавьте следующие строки:
Давайте разберёмся с этим кодом. Вы будете хранить информацию о всех подключенных пользователях в виде объектов JSON. Так как у каждого подключённого к серверу сокета есть уникальный id, клавиша будет представлять собой id сокета подключённого игрока. Значение же будет другим объектом JSON, содержащим координаты x и y .
Когда сервер получит сообщение о том, что присоединился новый игрок, он добавит новый вход в объект игроков при помощи id сокета, который будет в этом сообщении. Когда сервер получит сообщение о движении, то обновит информацию об игроке, который связан с этим сокетом, если он существует.
io.sockets.emit() — это запрос, который будет отправлять сообщение и данные ВСЕМ подключённым сокетам. Сервер будет отправлять это состояние всем подключённым клиентам 60 раз в секунду.
На данном этапе клиент ещё ничего не делает с этой информацией, поэтому добавьте со стороны клиента обработчик, который будет отображать данные от сервера в Canvas .
Этот код обращается к id Canvas ( #canvas ) и рисует там. Каждый раз, когда от сервера будет поступать сообщение о состоянии, данные в Canvas будут обнуляться, и на нём в виде зеленых кружков будут заново отображаться все игроки.
Теперь каждый новый игрок сможет видеть состояние всех подключенных игроков на Canvas . Запустите сервер командой node server.js и откройте в браузере два окна. При переходе по ссылке http://localhost:5000 вы должны будете увидеть нечто похожее:

Вот и всё! Если у вас возникли проблемы, посмотрите архив с исходным кодом.
Некоторые тонкости
Когда будете разрабатывать более функциональную игру, целесообразно разделить код на несколько файлов.
Такие многопользовательские игры — отличный пример архитектуры MVC (модель-представление-контроллер). Вся логическая часть должна обрабатываться на сервере, а всё, что должен делать клиент — это отправлять входные пользовательские данные на сервер и отображать информацию, которую получает от сервера.
Однако в этом демо-проекте есть несколько недостатков. Обновление игры связано со слушателем сокета. Если бы я хотел повлиять на ход игры, то мог бы написать в консоли браузера следующее:
Теперь данные о движении будут отправляться на сервер в зависимости от характеристик компьютера более 60 раз в секунду. Это приведёт к тому, что игрок будет передвигаться невероятно быстро. Так мы переходим к концепции определения полномочного сервера.
Ни на каком этапе клиент не должен контролировать какие-либо данные на сервере. Например, никогда не нужно размещать на сервере код, который позволит клиенту определять своё положение/здоровье на основе данных, которые передаются через сокет, так как пользователь сможет легко подделать сообщение, исходящее из сокета, как показано выше.
Когда я создавал свою первую многопользовательскую игру, я написал код так, что игрок мог стрелять тогда, когда отправлялось сообщение о стрельбе, которое со стороны клиента было связано с нажатием кнопки мыши. Умелый игрок мог воспользоваться этим, вставив строчку на JavaScript, очень похожую на ту, что упоминалась выше, чтобы заполучить почти неограниченную скорость стрельбы.
Лучшая аналогия, которую я могу привести, заключается в том, что клиенты должны посылать на сервер только информацию о своих намерениях, которые затем будут обрабатываться и использоваться для изменения состояния игроков, если они валидны.
В идеале циклы обновлений как у клиента, так и на сервере не должны зависеть от сокетов. Попытайтесь сделать так, чтобы обновления игры находились за пределами блока socket.on() . В противном случае вы можете получить много странных нелогичных действий из-за того, что обновление игры будет связано с обновлением сокета.
Кроме того, старайтесь избегать такого кода:
В этом отрезке кода обновление координаты х для игрока связано с частотой смены кадров в игре. SetInterval() не всегда гарантирует соблюдение интервала, вместо этого напишите нечто подобное:
Это не так изящно, зато обеспечит более плавную и последовательную работу. Усложните демо-проект и попробуйте сделать так, чтобы обновление осуществлялось согласно времени, а не частоте смены кадров. Если не захотите на этом останавливаться, попытайтесь создать на сервере физический движок, который будет управлять движениями игроков.
Также можно сделать так, чтобы из игры удалялись отключенные игроки. Когда сокет отключается, автоматически отправляется сообщение о разъединении. Это можно прописать так:
Также попытайтесь создать собственный физический движок. Это сложно, но весело. Если захотите попробовать, то рекомендую прочитать книгу «The Nature of Code», в которой есть много полезных идей.
Если хотите посмотреть на гораздо более продвинутый пример, вот игра, которую я сделал, а также исходный код, если вы хотите узнать, как это было написано. На этом всё. Спасибо, что прочитали!
Как создать простую браузерную игру с помощью Phaser 3 и TypeScript
![]()
Большую часть своего времени я занимаюсь backend-разработкой, поэтому я не могу похвастаться большим опытом во frontend. Какое-то время назад у меня возникло желание создать браузерную игру. Недолго думая, я выбрала Phaser 3 в качестве фреймворка (так как в настоящее время он достаточно популярен) и TypeScript в качестве языка программирования (потому что я предпочитаю статическую типизацию, а не динамическую). Оказалось, что нужно разобраться с огромным множеством скучных вещей, дабы все работало. Именно поэтому я написала эту статью, чтобы помочь таким же людям, как и я, быстрее приступить к самому интересному этапу.
Подготовка
Выберите среду разработки, в которой будете работать. Вы всегда можете использовать старый добрый Notepad++ если хотите, но я бы рекомендовала что-то более полезное. Лично я предпочитаю разрабатывать свои проекты в Emacs.
Если бы мы разрабатывали наш проект на JavaScript, мы бы прекрасно обошлись без всех этих подготовительных этапов. Однако, поскольку мы собираемся использовать TypeScript, нам нужно настроить инфраструктуру, чтобы в будущем разработка продвигалась как можно быстрее. Для этого необходимо установить Node.js и npm.
Во время написания этой статьи, я использую node 10.13.0 и npm 6.4.1. Обратите внимание на то, что в мире frontend-разработки все очень быстро меняется, поэтому старайтесь использовать самые последние стабильные версии. Я настоятельно рекомендую использовать nvm, вместо ручной установки node и npm, так как это позволит уберечь ваши нервы и сэкономить время.
Настройка проекта
Структура проекта
Для сборки проекта мы будем использовать npm, поэтому перейдите в пустую папку и запустите npm init . npm задаст вам несколько вопросов о свойствах вашего проекта, а затем создаст файл package.json . Это будет выглядеть примерно так:
Пакеты
Установите нужные пакеты с помощью следующей команды:
npm install -D typescript webpack webpack-cli ts-loader phaser live-server
-D (также известная как —save-dev ) заставляет npm автоматически добавлять эти пакеты в список зависимостей в package.json :
Webpack
Webpack запустит компилятор TypeScript и соберет кучу результирующих JS файлов, а также библиотек, в один уменьшенный JS файл, который мы сможем включить в нашу страницу.
Добавьте webpack.config.js рядом с вашим project.json :
Здесь мы видим, что webpack должен получить исходники (sources), начиная от src/app.ts (которые мы вскоре добавим), и собрать все в dist/app.js файл.
TypeScript
Также нам нужен небольшой конфигурационный файл для компилятора TypeScript ( tsconfig.json ), в котором мы объясняем, к какой версии JS должны быть скомпилированы исходники и где их найти:
TypeScript типы
TypeScript — это статически типизированный язык, следовательно, конечные типы переменных и функций устанавливаются на этапе компиляции. На момент написания этой статьи, типы для Phaser 3 еще не были доступны в виде nmp пакета, поэтому вам может потребоваться загрузить их из официального репозитория и поместить файл в подкаталог src вашего проекта.
Скрипты
Мы почти закончили настройку проекта. На данный момент вы должны были создать package.json , webpack.config.js и tsconfig.json , а также добавить src/phaser.d.ts . Последнее, что нужно сделать перед тем, как начать писать код — это объяснить, что конкретно npm должен сделать с проектом. Необходимо изменить раздел scripts файла package.json следующим образом:
При выполнении npm build , файл app.js будет собран в соответствии с конфигурацией webpack. И когда вы запустите npm start , вам не придется беспокоиться о процессе сборки: как только вы сохраните какой-либо исходник, webpack перестроит приложение, а live-server перезагрузит его в вашем браузере, стоящем по умолчанию. Приложение будет размещено по адресу http://127.0.0.1:8085/.
Начало работы
Итак, мы наконец можем приступить к написанию кода. На этом этапе мы сделаем одну простую вещь: нарисуем темно-синий прямоугольник в окне нашего браузера.
Позвольте мне кратко объяснить основные концепции Phaser 3. Игра является экземпляром класса Phaser.Game (или его потомком). Каждая игра содержит один или несколько экземпляров класса Phaser.Scene . Каждая сцена содержит несколько статических или динамических объектов, и представляет собой логическую часть игры. Например, наша тривиальная игра будет состоять из трех сцен: экрана приветствия, самой игры и экрана с очками, полученными за игру.
Давайте же приступим к написанию кода.
Перво-наперво, создайте простой HTML-контейнер для игры. Создайте файл index.html , который будет содержать следующий код:
Здесь есть два важных момента: первый— это тег script , который позволяет подключить какой-либо внешний js-файл и тег div , который представляет из себя контейнер для нашей игры.
Теперь создайте файл src/app.ts , в котором будет такой код:
Данный код не требует никаких пояснений. GameConfig содержит в себе большое количество свойств, на этой странице вы можете ознакомиться с ними.
Наконец вы можете запустить npm start . Если все было сделано правильно, вы увидите следующее в своем браузере:
Заставляем звезды падать с неба
Мы создали элементарное приложение. Теперь пришло время добавить что-нибудь интерактивное. Идея у игры простая: звезды будут падать на землю, а мы должны будем их ловить и чем больше, тем лучше.
Чтобы добиться этого, создайте новый файл gameScene.ts и добавьте в него такой код:
Метод constructor содержит в себе key, согласно которому другие сцены могут вызвать эту сцену.
Далее мы видим стабы для четырех методов. Позвольте мне кратко объяснить разницу между ними:
- init([params]) вызывается в тот момент, когда запускается сцена; эта функция может принимать параметры, которые передаются из других сцен или игры, путем вызова scene.start(key, [params])
- preload() вызывается до создания объектов сцены и содержит в себе loading assets (загрузочные ресурсы); эти ресурсы кэшируются, поэтому при перезапуске сцены они не перезагружаются
- create() вызывается, когда загружаются ресурсы (assets) и, как правило, включает создание основных игровых объектов (фона, игрока, препятствий, врагов и т.д.)
- update([time]) вызывается every tick (каждый кадр) и содержит динамическую часть сцены — все, что движется, мигает и т.д.
Пока не забыла, давайте быстренько добавим следующие строки в game.ts :
Теперь наша игра знает о GameScene. Если конфигурационный файл игры содержит в себе список сцен, тогда первая из них запускается при запуске игры, а все остальные создаются, но не запускаются до тех пор, пока их явно не вызовут.
Также мы добавили физический движок arcade physics. Это нужно для того, чтобы наши звезды падали.
Сейчас мы, так сказать, добавим мясо к костям нашей GameScene.
Во-первых, мы объявим некоторые свойства и объекты, которые нам понадобятся:
Затем мы инициализируем числа:
И загрузим пару изображений:
После этого мы можем подготовить наши статические компоненты. Мы создадим землю, куда будут падать звезды, и текст, информирующий нас о текущем счете:
Группы в Phaser 3 — это отличный способ создать группу объектов, которыми вы хотите управлять одновременно. Есть два типа объектов: статические и динамические. Как вы уже догадались, статические объекты не двигаются (земля, стены, различные препятствия), в то время как динамические наоборот (машины, ракеты, знаменитый итальянский водопроводчик).
Мы создадим статическую группу из кусочков земли. Эти кусочки расположены вдоль линии. Обратите внимание на то, что линия разделена на 20 одинаковых частей и плитки с землей расположены в каждой из этих частей. Также мы должны вызвать refresh() , чтобы обновить group bounding box (ограничивающий параллелепипед группы). В противном случае collisions (столкновения) будут проверены относительно местоположения по умолчанию, которое находится в левом верхнем углу сцены.
Если вы проверите, как выглядит ваше приложение, вы увидите нечто вроде этого:
Вот мы и добрались до самой динамичной части этой сцены — функции update() , в которой будут падать звезды. Мы хотим видеть падающую звезду каждую секунду, поэтому данная функция вызывается примерно один раз в 60 мс. Мы не будем использовать динамическую группу, поскольку жизненный цикл каждой звезды будет очень коротким: звезда будет уничтожена либо щелчком по ней пользователя, либо из-за столкновения с землей. Поэтому внутри функции emitStar() мы создаем новую звезду и добавляем обработку двух событий: onClick() и onCollision() .
Ура, у нас есть игра! Но все еще нет условий, которые нужны для победы. Мы добавим их в последней части нашей статьи.
Заканчиваем
Обычно любая игра состоит из нескольких сцен. Даже если ваш игровой процесс максимально прост, вам нужна вступительная сцена (например, включающая в себя кнопку “Играть!”) и заключительная сцена (например, показывающая ваш игровой результат). Давайте добавим эти сцены в наше приложение.
В нашем случае они будут очень похожи между собой, так как я не хочу уделять много внимания графическому оформлению игры. В конце концов, это просто туториал по программированию.
Вступительная сцена будет включать следующий код в welcomeScene.ts . Обратите внимание, что когда пользователь кликает в любом месте вступительной сцены — появляется игровая сцена.
Заключительная сцена будет выглядеть практически также. Нажатие в любом месте этой сцены приведет к появлению вступительной сцены ( scoreScene.ts ).
Теперь нам нужно обновить наш основной файл приложения: добавьте в него новые сцены и сделайте WelcomeScene первой в списке.
Вы заметили, чего не хватает? Правильно, мы все еще не вызываем ScoreScene из ниоткуда. Давайте сделаем так: сцена со счетом за игру будет вызываться после третьей пропущенной звезды:
Ну что же, наша игра “Starfall” выглядит как настоящая игра — она начинается, заканчивается и в ней есть цель (сколько звезд вы сможете поймать?).