Управление:

  • W - ускорение; 
  • Q - вращение влево; 
  • E - вращение вправо; 
  • AD - смещение в сторону; 
  • S - тормоз; 
  • 1 2 3 4 - смена пушек; 
  • клик - стрелять; 
  • space(пробел) - щит; 
  • ` (обратная кавычка), ё - выход в меню, пауза; 
  • esc - выход из полноэкранного режима.

Gameplay and screenshot

Project description

Собственно что реализовано в проекте:

По сути это игрушка в которой можно летать в космосе среди разных обьектов, метеоритов, космического мусора, стрелять по вражеским кораблям, который так же стреляют в ответ. Так же игрок не может пройти сквозь препятствие, в некоторых типах препятствий отнимается здоровье. Ограничено количество боеприпасаов, можно переключать оружие (4 вида, разные характеристики), можно собирать бонусы здоровья и боеприпасов. В игре присутствует несколько миссий, у миссий есть цели, они отображаются в игре и помечаются как пройденные или проваленые, выполнение определенной цели приводит к завершению миссии с победным звуком и экраном, так же возможен провал в случае уничтожения корабля игрока, в таком случае происходит выход в меню. В игре есть несколько миссий, они не особо продуманные, но демонстрируют возможности движка и геймплей. Так же перед запуском миссии выбирается один из доступных кораблей, каждый корабль имеет свою модель и модель внутреннего вида.

Управление в игре на кнопки W - вперед, QE вращение в бока, AD смещение в стороны, 1234 - выбор оружия, пробел - щит, клик - стрелять, esc - выход из полноэкранного режима, ё - пауза, меню. Так же дублируется экранным джойстиком для мобильных устройств.

На данный момент сохранено несколько версий игры от начала проекта, а так же предварительно написанная стрелялка до начала данного проекта. В последнюю версию к сожалению не удалось внедрить некоторые фичи предпоследней.

Так же доступны старые версии:

Team Member

Organization of the development process

Для распределения обязанностей и контроля над качеством и правильностью кода в команде должны присутствовать старшие или более опытные разработчики, в обязанности которых входит обсуждение функционала, постановка задачи и реализация и/или проверка написанного кода. Т.е. должен быть тимлид, который осуществляет распределение частей проекта между старшими разработчиками, просмотр кода, отслеживает сроки выполнения заданий, а так же создание новых при необходимости.
У нас в проекте тимлида не было и процесс разработки осуществлялся двумя разработчиками с разным уровнем знаний в программировании(т.е. был старший разработчик и младший разработчик). Поэтому, было решено делать всё на основе кода более опытного разработчика, т.е. младший разработчик пытался разобраться в коде старшего разработчика и на основе его кода сделать что-то своё в проекте.
Так как старший разработчик и младший разработчик работали в одних и тех же файлах, то для того, чтоб не было конфликтов при работе с github, было решено работать в разных ветках. Ветка старшего разработчика считалась основной, а младший разработчик должен был периодически клонировать ветку старшего разработчика и продолжать работать в клонированной ветке. В свою очередь старший разработчик забирал в свою ветку изменения из ветки младшего разработчика.
Старший разработчик работал над созданием движка игры и частично над вёрсткой (окно с игрой), над фичами. Младший разработчик также пытался реализовать фичи (например, аудиоплеер), создавал 3d-модели в 3ds max и делал текстуры для них, придумывал миссии и загружал модели в миссию 3, а также занимался вёрсткой (делал лендинг игры). (с)Младший разработчик.

На самом деле я много накосячил с гитом, надо было всетаки потиху в мастер сливать хороший код, и мержить было бы проще в таком случае. В целом младший разработчик крут. (с) Старший разработчик

employee photo

Alena Rebkavets

Начинающий frontend developer. Опыт в программировании: 6 месяцев. Высшее образование. Профессия: архитектор-визуализатор. Опыт работы в сфере проектирования зданий и сооружений: 9 лет. (+2 года чиновник).

icon facebook icon google icon linkedin icon Github
employee photo

Zhan Zhuridov

Frontend developer. Engineer of electronics. More 10 years of programming experience.

icon facebook icon google icon linkedin icon Github

Organization of the development process

Для распределения обязанностей и контроля над качеством и правильностью кода в команде должны присутствовать старшие или более опытные разработчики, в обязанности которых входит обсуждение функционала, постановка задачи и реализация и/или проверка написанного кода. Т.е. должен быть тимлидер, который осуществляет распределение частей проекта между старшими разработчиками, просмотр кода, отслеживает сроки выполнения заданий, а так же создание новых при необходимости.
У нас в проекте тимлидера не было и процесс разработки осуществлялся двумя разработчиками с разным уровнем знаний в программировании(т.е. был старший разработчик и младший разработчик). Поэтому, было решено делать всё на основе кода более опытного разработчика, т.е. младший разработчик пытался разобраться в коде старшего разработчика и на основе его кода сделать что-то своё в проекте.
Так как старший разработчик и младший разработчик работали в одних и тех же файлах, то для того, чтоб не было конфликтов при работе с github, было решено работать в разных ветках. Ветка старшего разработчика считалась основной, а младший разработчик должен был периодически клонировать ветку старшего разработчика и продолжать работать в клонированной ветке. В свою очередь старший разработчик забирал в свою ветку изменения из ветки младшего разработчика.
Старший разработчик работал над созданием движка игры и частично над вёрсткой (окно с игрой), над фичами. Младший разработчик также пытался реализовать фичи (например, аудиоплеер), создавал 3d-модели в 3ds max и делал текстуры для них, придумывал миссии и загружал модели в миссию 1, а также занимался вёрсткой (делал лендинг игры).

Technical problems

Основными сложностями в проекте можно называть:
  • 1. Требования к производительности
  • 2. Необходимость учитывать медленное соединение с интернетом
  • 3. Объем кода
  • 4. Длительность тестирования
  • 5. Математическая сложность

1. Требования к производительности

Требования к производительности для реалтайм графики один из самых сложных моментов, к тому же это был первый мой проект с использованием WebGL технологии. Типичный цикл web программирования заключается в создании, удалении объектов из DOM, навешивании обработчиков, смене аттрибутов элементов. Браузер при этом сам перерисовывает страницу и об этом не надо беспокоиться. В случае работы с canvas, в частности с контекстом webGL задача рендеринга с частотой 60 кадров в секунду ложится на разработчика. С такой скоростью JS может выполнять не так и много операций, ориентировочно цикл for с 30к - 100к итераций уже вызовет просадку fps. WebGL решает эту проблему при отрисовке сложных моделей шейдерами - специальными программами на языке GLSL, выполняемыми непосредственно на GPU. Так js вызывает лишь некоторые функции подготовки видеокарты к рендерингу, заполняет буферы, загружает текстуры, указывает необходимые шейдерные программы, устанавливает значения входных переменных шейдеров и наконец запрашивает отрисовку. Все эти действия так же занимают время, но далеко не все параметры надо устанавливать каждый кадр, на этом была построена одна из оптимизаций. Другой момент - шейдеры не могут возвращать результат, результат их работы отображается на canvas. Конечно была идея попробовать прочитать отдельные пиксели для возможности вести расчеты через GPU, но задача показалась сложной и возникали некоторые сомнения. Таким образом было решено физику рассчитывать на JS, по сути выполнять тоже что делает вершинный шейдер. И так изобразим путь графических объектов от сервера до пользователя: Сервер - интернет - оперативная память (полученные Obj, png) - парсер obj - загрузка в видеопамять (буффер вершин, текстура, шейдер) - установка шейдера - установка буфера - установка трансформов - отрисовка. Из этих всех операций в реальном времени можно выполнять лишь последние 4. Но даже частая смена текстур и моделей и конечно же шейдеров времязатратно, поэтому было решено предварительно создать дерево рендеринга таким образом, что сначала устанавливается шейдер и рисуются все буферы с ним связанные, причем они могут отрисовываться несколько раз с разными матричными трансформами. Это дало значительный прирост к скорости. С физическими моделями и проверкой столкновений так же добавились сложности, ведь их надо рассчитывать каждый кадр тоже. Основная сложность в том, что рендеринг выполняется линейно для всех моделей, а физика считается квадратично, взаимодействие каждой с каждой. Но есть часть вычислений, которые можно предварительно рассчитать для каждой модели. Так выделилось 3 функции: render - отрисовка process - предварительный расчет физики react - взаимодействие физических моделей Но объекты могут быть разных категорий, например пули взаимодействуют со всеми объектами, враги и игрок могут реагировать на столкновения с твердыми объектами, игрок может собирать бонусные объекты и чекпоинты. Поэтому аналогично рисовке, физические модели были представлены в виде списков для каждой категории. Получается один объект по сути мог находиться в разных списках, а иногда их требовалось удалять полностью. Так был создан базовый игровой объект, который можно было привязать к разным спискам для задания ему свойств, объект хранил ссылки на все списки в которых он находится и позволял удалять себя из всех. Некоторые объекты могут иметь собственные события например onHit, onKilled, onContact и принимать обработчики подобно dom объектам. Таким образом многие проблемы с игровыми объектами были решены. Конечно медленность физических расчетов осталась, она требует более глубокого решения, например есть возможность использовать упрощенные модели для физики и более сложные для отрисовки и объединять их в класс.

2. Необходимость учитывать медленное соединение с интернетом

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

3. Объем кода

Проект оказался очень огромным, впервые мне удалось написать настолько много кода. В проекте около 50 рабочих js файла со средним числом строк около 100, при этом во время разработки код сильно менялся, 2 раза перестраивалась вся архитектура и много кода полностью переписывалось, таким образом ушло из проекта около 70 js файлов. Тем не менее продакшн сборка самого скрипта всего 150кб при наличии в нем кучи разных объектов, сложнейшей математики, кучи линков на внешние файлы. А это как размер одного слайдера из интернета. Проект развивался быстро, всегда хотелось получить результат, были случаи, что для возможности протестировать приходилось писать более 300 строк кода, промежуточные тесты были невозможны. Не всегда хотелось тратить время на написание хорошего кода для проверки фич, которые с некоторой вероятностью могли оказаться неработоспособными. Рефакторинг же приводил к тому, что изменений требовалось много по всему коду, и иногда это сразу не делалось, так накапливася легаси код, например обьекты в игру можно было добавлять как старыми методами так и новыми. Так же такой объем кода не был изначально сгруппирован по папкам, получалась каша, поиск нужных файлов занимал все больше времени, и все это приходилось держать в голове. Впринципе я весь месяц держал в голове весь код и всегда мог сказать в какой папке, в каком файле и на какой приблизительно строчке что можно найти. Тем не менее высокая связность модулей, разбросанность фич вносила сложности в редактирование и вытекает следующий пункт

4. Длительность тестирования

Данный пункт можно разбить на 3 подпункта

  • а. большой объем приложения, длительный доступ к нужной странице или нужной позиции или ситуации в игре.
  • б. разбросанность кода требует вносить множество правок для испытания новой фичи
  • в. некоторые функции, например мультитач управление, фуллскрин требует испытания на настоящей мобиле, а не симуляторе.
Таким образом некоторые фичи реализовывались отдельно от общего кода, создавались наброски игровых меню, отдельная верстка, которая потом переносилась на существующие классы, привязывалась к логике приложения. Создавались специально тестовые расстановки объектов для испытания взаимодействий в игре.

5. Математическая сложность

Для многих уверен это может показаться странным, но да, создание 3d игр это чертовски сложная математика. Если быть кратким то рассмотрим пример, пусть у нас есть кубик и есть пуля летящая в него в виде точки по линейной траектории, и на все это смотрит камера и с нее мы видим изображение. Так вот кубик состоит из 8 точек, обьединенных индексами в треугольники, каждая точка содержит как минимум 3 координаты, а так же может содержать нормали, текстурные координаты, другие параметры. Так вот попадание пули - результат решения уравнения плоскости каждого треугольника с параметрическим уравнением прямой траектории пули, с проверкой попадания решения этой системы одновременно в треугольник и отрезок для текущего перемещения за кадр. Допустим пуля должна отскочить, тогда требуется рассчитать новый вектор скорости повернутый на угол отражения относительно нормали треугольника, например через скалярное произведение вектора скорости и вектора нормали. А если смотреть на это все камерой, то для отображения на экране необходимо умножить все вершины этого куба на матрицу его трансформа, на матрицу трансформа камеры и на матрицу проекции. А пулю пересекать так же с трансформированным объектом зачастую надо. И это впринципе не сложно, в некоторых случаях используются экспоненты и логарифмы, но не чисел, а матриц, например для интерполяции трансформов при анимации. Иногда всего этого очень много.

Итог:

Было сделано много, хоть можно было и лучше. Проект был просто пределом возможностей, вклад вносился ежедневно на протяжении более месяца, приходилось часто не спать, иногда нервы были на пределе, когда приходилось терять драгоценное время на деградационно-ориентированной работе. Важной фичей является адаптивность и кроссплатформенность. Приложение тестировалось в Firefox (основной), Chrome, а так же на мобиле тоже Chrome. Мобильная версия требовала свое управление в виде экранного джойстика. Так же адаптивности верстки всего сайта и игровых элементов. Использование мультитач потребовало переработать класс кнопки, onClick событие не работает с мультитачем, требуется обработка полностью touch событий. Так же mouseMove сильно отличается от touchMove. У второго довольно высокий порог срабатывания, так перемещение становится дерганым, поэтому решено было управлять не самим вращением камеры, а ее скоростью, так получилось играбельно. Так же много юзабельности дало полное заполнение экрана невидимыми чуствительными областями и размещение небольших иконок над ними. В целом на копийность прототипа упор не делался, взята была основная тематика, развивалась отдельная игра со своей механикой, большим вниманием к мобильной версии, в связи с этим упрощением управления, адаптации игровых меню. Вроде что-то получилось.