Возможно ли разрабатывать игры без движков, фреймворков?
Возможно ли написание игры без использования класса
Вобщем это мой первый проект. До этого вобще не чего не писал. Возможно ли написание данной.
Если изучить Delphi, то возможно ли, разрабатывать программы на Pascal?
Если изучить Delphi, то возможно ли, разрабатывать программы на Pascal? В какой среде.
GUI без фреймворков
Появилось желание обернуть программку в GUI(да и чего греха таить, в целом научиться делать.
Python без фреймворков
Друзья, только начал изучать Python, подскажите пожалуйста — возможно ли писать сайты на Python без.
На чем лучше разрабатывать игры с помощью Delphi.
Привет уважаемые программисты Delphi! Я хотел спросить на чем лучше разрабатывать игры с помощью.
Как считывать видео без фреймворков?
Есть задача считывать видео. Те открывать в программе и считывать его как в bitmap картинку только.
Подключение к dbf без специальных движков
Добрый день! Использую таблицы формата dbf. при подключении через ADO с помощью VFPOLEDB.
С чего нужно начинать, чтобы полноценно научиться разрабатывать программы и игры
Уважаемые форумчане помогите обычному парню освоить С#. Посоветуйте с чего нужно начинать, чтобы.
Как создать раздел на сайте без движков
Есть сайт test.ru. Я хочу, чтобы на нем были определенные разделы, типа site.ru/info или.
Вёрстка адаптивного меню-гамбургер без использования фреймворков
Всем привет! Необходимо сверстать адаптивное гамбургер-меню без использования фреймворков.
Как упростить разработку игры в одиночку — несколько полезных советов для новичков Статьи редакции
Создатель инди-игры Svarog’s Dream под ником Lynxbird опубликовал на Reddit список советов для соло-разработчиков. В основном они касаются организационных вопросов, которые помогают упростить рабочий процесс. Выбрали из текста главное.
Постарайтесь потратить утреннее время на разработку, а не на проверку соцсетей или новостей. Это особенно важно, если у вас есть ещё и основная работа. Если рабочий день начинается в 8 утра, вставайте в 6 утра и посвятите хотя бы час разработке — это именно то время суток, когда у вас ясная голова.
Каждый день делайте хотя бы что-то, связанное с проектом. Если вы сделаете перерыв на несколько дней или недель, есть большая вероятность, что вы выйдете из потока и в итоге просто забросите разработку. При этом стоит чередовать занятия. Например, если вам надоело программировать, займитесь артом. Перерывы тоже можно делать, но даже в такие моменты вы можете искать идеи для своего проекта в телешоу, книгах, других играх.
Создайте базовый документ, описывающий то, что вы хотите сделать. Это поможет вам воплотить идею и станет напоминанием о том, какая у вас конечная цель. Также это поможет вам легче объяснить другим разработчикам, о чём ваша игра. Lynxbird создал шаблон, который поможет описать идею. Если у вас возникли затруднения при заполнении каких-то пунктов, то это, вероятно, значит, что вам надо ещё подумать над концепцией.
Используйте ассеты из магазинов (хотя бы для прототипа). Даже крупные студии применяют сторонние ассеты, когда надо сделать какие-то не слишком важные вещи: например, природу или другие элементы окружения. Соло-разработчикам не обязательно тратить пять рабочих дней на создание текстуры грунта, когда её можно бесплатно взять из какой-то библиотеки. Экономьте время там, где можете.
Используйте систему управлениями версиями. Можно использовать стандартный Git — он бесплатный и имеет неограниченное пространство для хранения. Если ваш проект занимает больше, чем несколько гигабайт, то стоит подключить Git Large File Storage. Это позволит вам без проблем экспериментировать со своей игрой, и в случае ошибки вы сможете легко вернуться к предыдущей версии.
Оставляйте комментарии. Можно это делать в специальном сервисе, например, Jira, Azure Devops Backlog, или же просто записывать на бумаге. Фиксируйте там новые идеи, отмечайте, чем занимались в последний раз, чтобы потом было проще разобраться. Если вы столкнулись с ошибкой и не хотите исправлять её сейчас, опишите её и продолжайте заниматься текущей задачей.
При создании прототипа не переусложняйте вашу игру. Добейтесь того, чтобы основные фичи работали, но при этом применяйте самые простые решения. Уже после вы сможете всё переделать, чтобы улучшить игру. Не тратьте месяц на создание системы, которая потом окажется лишней и вы просто её выкинете.
Как можно раньше получите фидбек. Соло-разработчики легко могут стать субъективными и потратить много времени на по-настоящему плохую идею. Вы можете представить вашу игру в соцсетях и посмотреть на отклик пользователей. Это даст вам хотя бы какое-то понимание, идёте ли вы правильном направлении или нет. Покажите игру своим друзьям или семье.
Но помните, что в этом деле важно количество отзывов. Если одному человеку не нравится ваша боевая система, то этого ещё ничего не значит. Если же 10 человек из 20 скажут, что боевая система и правда плохая, то вам, возможно, стоит её переделать.
Занимайтесь продвижением одновременно с разработкой. До релиза у вас есть время, чтобы собрать лояльную аудиторию и показать игру как можно большему числу людей. Попытайтесь привлечь внимание: например, опубликуйте гифку с милым существом из вашей игры. Используйте Imgur, Discord, Twitter, Instagram, Facebook и другие соцсети. Чаще всего на полноценный маркетинг у вас не хватит денег, поэтому придётся проявить творческий подход.
Не гоняйтесь за новейшими технологиями. Вышла новая версия движка? Появилась новая версия IDE, новые 3D-инструменты, новая языковая библиотека, доступен новый пайплайн для рендеринга? Не спешите переходить на них. Оцените ресурсы, которые вам придётся вложить, чтобы разобраться в новом инструменте. Если выгода перевесит затраты, то оно того стоит. Если нет, то не тратьте на это время.
Не доверяйте всему, что вы читаете. Люди могут ошибаться, какие-то решения и советы могут не подойти конкретно вам. Относитесь ко всему критически.
А какие советы можете дать вы? Поделитесь ими в комментариях.
Хотите реально нормальные советы, а не эту воду)? Это связано в первую очередь с корованами на UE4 в одиночку, если уж вы решили делать какой — нибудь клон готики или упаси боже соулс лайк (ведь у вас не получится сделать нормальную боевку, многие пытались)
-Разбейте разработку механики на этапы и тестите после каждого микроизменения кода (так можно мгновенно пофиксить новообразованный баг или перебирать галки/функции пока не получится запилить что — то рабочее)
-Меню, выбор уровня и настройки делайте в последнюю очередь перед релизом т.к отнимает время от тестирования сцены.
-Создайте для себя простую модульную структуру для проекта которую можно расширять.Наследование тоже не забывайте, например у предметов в инвентаре должен быть общий класс (item) в который забиваются данные с бдшки, у персонажей общий контроллер который включает базовые вещи типо ходьбы и т.д.
-Ядро и интерфейс всегда должны быть отдельно (например инвентарь).
-Как можно больше данных забивайте в БДшки чтоб не грузить гиперклассом движок и быстро менять кучу данных без крашей от зависимостей (например предметы в инвентаре, классы персонажей, описания, тексты и т.д).
-Сделайте свою абилити систему, если планируется больше 3-5 способностей/интерактов/пасивок в игре, разбивать код на абилки удобнее чем держать все в одном гиперклассе / полотне блупринтов.
-Никогда не юзайте ассеты с кодом (если они не модульные), потому что они написаны индусским говнокодом и переделать их будет невозможно.
-По той же причине никогда не юзайте плагины если можно обойтись без них, потому что апдейты на плагины выходят раз в год (если вообще выходят), а чтобы их переделать нужно ещё и знать как паковать плагины, если вообще получится в этом разобраться.
-Тестите ассеты в "йохохо" версиях перед покупкой, потому что нельзя быть уверенным что подойдет игре, а что нет, вполне вероятно придется с пяток вариантов перебрать прежде чем поймешь что реально подходит и может интегрироваться в проект без конфликтов.
спасибо, полезные советы! Будет классно, если вы дополните этот комментарий и превратите в полноценный пост. Уверен, что это поможет многим начинающим разработчикам
Можешь подсказать на основе своего опыта, стоит ли писать всю логику на C++ или же лучше для основной логики использовать блупринты, а C++ только при острой необходимости? В прошлом встречался с проблемой высокой сложности рефакторинга кода на BP. Пытался все писать на плюсах, но здесь уже вылезали проблемы с ожиданием долгих компиляций, увеличением сложности и времени разработки фичей.
Respect. Сам до таких же выводов дошёл, но потребовалось время
Не, ну это статья должна быть, пусть и короткая 🙂
Совет мега полезный
Будьте талантливы во всём.
Делайте хорошо и не делайте плохо
иронично, что этот совет лучше тех, что в статье и уже какой раз повторенных
Совет про утро так себе, у всех разное время максимальной эффективности.
Встать в 6 утра и поработать до основной работы, хуже совета сложно придумать. Как делать домашнее задание до школы.
почему-то так говорят только те, кто ленится рано вставать
В этот момент я понял, что последним советом будет являться "никому не верьте"
Я в шесть утра только спать ложус
Голова в целом ясная, как у Будды. Сплошной пустырь в ней в шесть утров
Смотря когда ложишься спать
Вот этот совет "При создании прототипа не переусложняйте вашу игру. Уже после вы сможете всё переделать, чтобы улучшить игру" весьма спорный, так как чреват переделкой с чистого листа из-за архитектурных упущений при разработке упрощенного прототипа. Не каждый начинающий разработчик (а судя по тексту, это советы именно для них) сразу сможет в модульность и расширяемость.
Прототип про проверку работы механик, а не их архитектурно правильную реализацию. Если механика будет плохо встраиваться в игру или будет просто скучной, то какой смысл от того, что она сделана как по учебнику? Она целиком будет выкинута в мусорку.
Прототип по хорошему как раз полагается выкинуть и переделать с чистого листа потом.
У желания сделать все хорошо, есть проблема никогда ничего не начать.
Я тоже думал, что сова пока не начал ложиться до 12. Человеку не свойственно бодрствовать ночью.
Разработка браузерной онлайн игры без фреймворков и движков

В этом посте будет описан процесс разработки онлайн игры на чистом javascript и WebGL (без фреймворков и движков). Будут рассмотрены некоторые алгоритмы, техники рендеринга, искусственный интеллект ботов и сетевая игра. Проект является полностью опенсорсным, в конце поста будет ссылка на репозиторий.
Сразу же геймплейное видео:
Тут играет бот по имени Лягуха и другие боты
Введение
Игра представляет из себя 2D стрелялку «вид сверху». В игре присутствуют следующие элементы: земля; стены, ограничивающие видимость; лава, по которой ходить нельзя; мосты через лаву; 6 видов оружия и 5 видов пауэрапов; персонажи, одним из которых управляет игрок.
Геймплей, как в Quake III, обычный deathmatch, то есть нужно убить врагов больше, чем это сделают они. В игре присутствуют боты, но как только в неё заходит живой игрок, то один из ботов удаляется (тот, кто недавно погиб и не успел еще респавниться). Набор оружия традиционен для подобных игр. Стоит отметить лишь, что рельса наносит бесконечный урон, а ракетница стреляет «умными» ракетами — они подрываются автоматически, когда пролетают на минимальном расстоянии от врага.
Клиент написан на javascript с использованием WebGL, а сервер на node.js. В этом проекте используются следующие библиотеки:
-
— для requestAnimationFrame, fullscreen и mouselock — матричная библиотека — звуковая библиотека
- bootstrap и jquery сугубо для странички с вводом ника, более нигде не использовались
- на сервере используется express, ws (WebSocket) и другие
Генерация уровня
Для генерации карты используется обычный Шум Перлина плюс некоторые преобразования и фильтрации:

Где perlinNoise() — шум Перлина, в диапазоне от 0 до 1,
abs(x) — модуль числа,
clamp(x) — если x < 0, то x = 0. Если x > 1, то x = 1,
norm(-0.5, 2) — нормализует шум в данный диапазон.
Именно такая последовательность преобразований на выходе даёт требуемую топологию карты: она состоит из комнат и коридоров, шириной в 2-3 пикселя.
Получившаяся текстура является маской земли (черный цвет — земля, белый — стена).
Далее в отдельном буфере генерируется река лавы. Для этого генерируется ломаная (если нужны притоки, то несколько ломаных) и каждый отрезок ломанной «рисуется» в буфер с помощью алгоритма Брезенхама. Затем этот буфер с отрезками размывается по Гауссу. Радиус размытия выбирается исходя из требуемой ширины реки. Для оптимизации размытия используется двухпроходный алгоритм. Функция размытия нам ещё не раз пригодится. Размытие буфера с лавой нужно для того, чтобы придать реке ширину, а так же в дальнейшем для рендеринга.
В маске земли, где проходит лава и в непосредственной близости от неё, удаляются стены:
Слева направо: маска земли с предыдущего этапа; маска лавы; расчищаем стены от лавы; финальный результат
Перед тем, как получить этот самый финальный результат, над маской земли проводятся несколько преобразований: фильтрация мелких деталей (стены и проходы шириной в один пиксель нежелательны); заливка изолированных областей (в процессе генерации могут образоваться зоны полностью изолированные стенами со всех сторон, их лучше залить белым, чтобы игроки там не спавнились); по краям добавляется слой стен шириной в 5 пикселей, чтобы игроки не сбежали с карты.

Ну и в конце генерируются мосты. Тут все просто: выбираются случайные точки на лаве так, чтобы мосты не были слишком близко друг к другу или слишком далеко, и ориентируются они перпендикулярно потоку лавы в данной точке (естественно мосты не запекаются в левелмапу, они хранятся просто как массив объектов).
Помимо масок земли и лавы генерируются еще две вспомогательные: маска для текстур (т.к. в игре на землю накладываются две разные текстуры, эта маска задает коэффициенты смешивания этих текстур) и маска статичных теней от стен. Маска для текстур — это всё тот же шум Перлина.
Перед тем, как маску земли запечь в левелмапу её следует размыть по Гауссу. Это нужно для создания плавных контуров.
Все вышеперечисленные маски и составляют нашу левелмапу. Вот из чего она состоит: R канал содержит маску лавы; G — маска земли; B — маска для смешивания диффузных текстур; A — тени.

Рендеринг уровня
Если прямо сейчас взять и отрендерить левелмапу, то получится примерно следующее:

Слева прямоугольник на левелмапе показывает охват камеры
Как такое получить? Допустим у нас есть матрица камеры (мы же точно знаем позицию своего игрока и угол его поворота). В вершинном шейдере эта матрица умножается на текстурные координаты полноэкранного квада, а результат передаётся во фрагментный шейдер. Эти текстурные координаты ни что иное, как координаты фрагмента внутри левелмапы. Поэтому просто делаем выборку из неё по этим координатам. На скриншоте выше выводятся только RG каналы левелмапы.
Получилось слишком размыто (фильтр Гаусса даёт о себе знать). Давайте к результату выборки из левелмапы применим клампинг:
Смысл этой формулы: level.rg у нас меняется плавно от 0 до 1 (видно на скриншоте выше). После клампинга все значения выборки меньшие 0.5 обращаются в 0, а большие 0.516 обращаются в 1, а значения на отрезке [0.5, 0.516] «растягиваются» в отрезок [0, 1]. Вот так это выглядит:
Пришло время для текстур: две диффузные текстуры смешиваются по маске из B-канала левелмапы, с ними смешивается текстура стены по G-каналу, а получившийся результат смешивается с текстурой лавы по R-каналу левелмапы (смешивание цветов в шейдерах GLSL производится функцией mix — это обычная линейная интерполяция двух значений по коэффициенту смешивания). Для выборки из текстур используется всё те же текстурные координаты домноженные на некий коэффициент, который влияет на количество повторений этой текстуры по всей карте:
Всё выглядит слишком плоским. Чтобы это исправить в наш шейдер нужно передать ещё одну текстуру с шумом Перлина. Выборку из этой текстуры прибавляем к значению R-канала левелмапы (маска лавы). Получившийся коэффициент используется не только для смешивания лавы и земли, но и для затенения береговой линии. Также добавим статические тени, которые хранятся в A-канале левелмапы:
Выглядит уже лучше, обратите внимание как преобразилась береговая линия, теперь она не такая ровная и плоская.
Осталось решить последнюю проблему: мы можем видеть через стену (то есть видим области, которые отгорожены стеной от нашего персонажа). Для решения этой проблемы используется трассировка фрагмента: из исследуемого фрагмента выпускается луч в сторону персонажа и делаются выборки из левелмапы (нас интересует только G-канал с маской стены), в данном проекте используется 12 выборок. По результатам выборок можно определить, виден ли фрагмент из позиции персонажа или нет. Для полноэкранного прохода такая трассировка слишком дорогая операция, поэтому она выполняется в отдельном фреймбуфере малого размера (64х64). Эта текстура называется картой видимости:

До применения карты видимости и после
Карта видимости используется не только в полноэкранном проходе для рендеринга карты, но и для рендера всех игровых объектов (мосты, пушки, персонажи).
Рендеринг лавы
Теперь давайте анимируем лаву. Для этого нужно создать карту смещений. В этой текстуре в RG-каналах хранится 2D вектор, который складывается с текстурными координатами для выборки из текстуры лавы. Причем нужна не просто карта смещений, а карта смещений меняющаяся со временем. В данной игре для создания карты смещений используется фреймбуфер размером 512х512. В шейдер этого прохода передаётся текстура с шумом Перлина и время, измеряемое от 0 до 1.
Кусок фрагментного шейдера (упрощено):
где noise — шумовая текстура (она статичная).
Смысл этого шейдера в том, что делаются 4 выборки из одной и той же шумовой текстуры, но с разным масштабом текстурных координат. Да ещё и смещаются они со временем в перпендикулярных направлениях (обратите внимание на вторую выборку, там используется смещение time.yx, а в первой — time.xy). Время зашито только в x-компоненту переменной time, а y-компонента содержит 0.
Теперь эту анимированную текстуру можно передать в шейдер лавы. В этом шейдере делаем выборку из карты смещений и прибавляем полученный 2D вектор к текстурным координатам лавы.
Упрощенный кусок шейдера:
где tex_wave — карта смещений (ну или карта волн).
С коэффициентом 0.1 можно поиграться, влияет он на «возмущение» лавы.
В принципе, на этом можно было бы и остановиться, выглядит довольно неплохо. Но можно сделать ещё лучше — заставить лаву течь. Для создания течения нам понадобится сгенерировать ещё одну текстуру: карту скоростей. Когда генерировалась лава, мы создали ломаную и нарисовали отрезки этой ломаной в буфер лавы. Теперь заведем ещё один буфер для карты скоростей. Нарисуем в него отрезки ломаной, но при этом каждый отрезок будет заносить в этот буфер вектор направления отрезка. Затем размоем этот буфер по Гауссу, тем самым мы не только «размешаем» скорости на изломах реки и на пересечениях с притоками, но и получим эффект «вязкой лавы», то есть скорость потока лавы в середине реки выше, чем у берегов.

Карта скоростей используется для смещения текстурных координат лавы. Чтобы появился эффект течения, смещать нужно с учетом времени.
Итак, обновленный шейдер лавы (упрощено):
Тут делается две выборки из текстуры лавы на расстоянии друг от друга в точности равное vel.xy и смешиваются по значению времени.
Всё вместе выглядит так:
Декали в данной игре — это лужи крови, следы от взрывов ракет и других пуль.
Декали, как объекты, сами по себе нигде не хранятся и не процессятся. Каждая декалька, в момент своего появления, рендерится в огромную текстуру, которая покрывает всю карту. Эта текстура потом «натягивается» на левелмапу. То есть, она содержит в себе все когда либо появлявшиеся декали (естественно она не чистится).
Теперь давайте выясним, какое разрешение должно быть у этой текстуры с декалями. Экспериментальным путём было выяснено, что 16х16 текселей текстуры, приходящиеся на один тайл карты выглядит оптимально (если брать 32х32, то это уже больше, чем размер самой декальки, например следа от взрыва, а по памяти 4-кратный проигрыш). Самая большая карта имеет размер 256х256, тогда разрешение текстуры с декалями равно 16 * 256 = 4096х4096.
На самом деле текстура 4К*4К не создаётся, вместо этого всю карту «распиливаем» на зоны 32х32. На каждую такую зону приходится собственная текстура с декалями 512х512. Всего таких текстур для большой карты 64. Чтобы не передавать пачку этих текстур в главный проход рендеринга карты (и не процессить из какой именно делать выборки) был создан ещё один фреймбуфер. Для него настраивается ровно та же матрица камеры, что и для рендеринга карты. И все текстуры с декалями по-очереди рендерятся в неё с учётом своих позиций на карте (естественно большая часть из них отсекается до вызова drawcall). Теперь в главный проход рендеринга карты передаём только этот готовый фреймбуфер.
Физика
Чтобы определить факт столкновения некой точки со стеной или попадание точки в лаву, нужно прочитать значение из массива с размытой левелмапой по целочисленным координатам этой точки, а так же по соседним координатам. Вручную произвести линейную интерполяцию этих значений и сравнить с неким пороговым значением.
Для определения нормали к стене в точке (X, Y) нужно произвести такую операцию трижды: для точек (X, Y), (X + 0.25, Y), (X, Y + 0.25):
Нормали используются не только для вычисления рикошетов, но и для столкновения персонажа со стеной. Когда персонаж пересекает корпусом стену, то в этом же кадре его как бы выпихивает по направлении нормали.
Преимущества и недостатки использования левелмапы по сравнению с тайловым рендером.
- Рендерится одним вызовом и всё в одном шейдере
- Легко создавать неровности и плавные переходы, физика при этом не страдает
- Бесплатный антиалиасинг
- Не нужно хранить тонну тайлов и думать о том, как их отсечь по камере
- Что-то ещё
- Рендерится одним вызовом и всё в одном шейдере, поэтому он довольно тяжелый
- Мы ограничены в диффузных текстурах, потому что маски смешивания нужно помещать в каналы левелмапы, коих всего 4. Ну и в целом труднее создать разнообразие на карте
- Что-то ещё
Искусственный интеллект ботов
Первая и самая главная задача ИИ ботов — это научить их просто бегать по карте, не обращая внимание на врагов и предметы. То есть адекватное перемещений по коридорам и комнатам, а так же по мостам через лаву. Для этого используется специальный граф, узлы которого назовём вейпоинтами. Такой граф должен покрывать всю карту, проходить через все коридоры и комнаты. Бот просто имеет ссылку на текущий вейпоинт, и, когда достигает его, выбирает случайным образом следующий вейпоинт из тех, на которые ссылается его текущий. Выглядит вроде просто. Но сначала нужно построить этот граф вейпоинтов.
Итак, у нас есть маска земли и маска лавы. Сложим эти две маски, чтобы получить карту проходимости (далее именно с ней и будем иметь дело при построении графа).

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

Тут на картинке в цвете закодировано расстояние, чем темнее, тем дальше
В принципе, тут уже угадываются очертания будущего графа. Следующий подготовительный этап — это вычисление градиента карты расстояний. Где градиент близок к нулю, там и будет вейпоинт.
Градиент карты расстояний в точке (i, j) вычисляется примерно так:
Т.о. для всех пикселей карты выполняем этот код (на самом деле только для проходимых пикселей).
Градиент карты расстояний:

Тут, по традиции, RG-каналы кодируют вектор
Эта карта напоминает горный хребет. Идея состоит в том, чтобы раскидать вейпоинты в точках, где проходит гребень этого хребта. А как найти гребень? Компоненты вектора градиента изменяются от -1 до 1. Гребень хребта будет там, где градиент находится в диапазоне [-α, α], где α — некая константа, подбираемая экспериментальным путём (в данном проекте равна 0.4). Все точки, в которых удовлетворяется данное условие будут первым приближением ко множеству вейпоинтов. Помимо «гребневых» вейпоинтов также добавляются по два вейпоинта для каждого моста (в точках, где мост опирается на землю). Карта с вейпоинтами:

Зелёные точки — это вейпоинты
Вейпоинты расположились слишком густо. Некоторые из них нужно удалить. В данном проекте минимально допустимое расстояние между вейпоинтами равно 4 пикселя. Поэтому перебираем все пары вейпоинтов и если расстояние меньше допустимого, то удаляем один из них. Естественно пропускаем мостовые вейпоинты, т.к. они никогда не должны быть удалены.

Теперь необходимо соединить эти вейпоинты рёбрами. Перебираем все пары вейпоинтов и соединяем пару ребром тогда, когда оба вейпоинта видимы друг из друга. Для определения видимости используется трассировка: делаем n выборок из карты проходимости вдоль отрезка, соединяющего эти вейпоинты; где n — длина отрезка. Если все выборки дали проходимый пиксель, то соединяем эти два вейпоинта ребром:

Красные линии — это рёбра графа
Получилось слишком много лишних рёбер. Для решения этой проблемы нужно избавиться от треугольников. Как это работает? Возьмём любое ребро с двумя вейпоинтами A и B. Допустим среди соседей A есть вейпоинт C, который в свою очередь является и соседом B. Т.е. образуется треугольник ABC. Самое длинное ребро этого треугольника нужно удалить. То же самое проделываем для всех рёбер:

Некоторые вейпоинты не связаны ребрами с другими — они отфильтровались. Также на картинке видно, что одно ребро прошло по мосту через лаву
Это окончательный граф. Теперь каждый бот может по нему навигироваться.
ИИ бота состоит из стейтмашин, всего их три. Одна стейтмашина задаёт общее состояние бота, а две другие управляют двумя степенями свободы: ноги (перемещение) и корпус. На выходе ИИ бота выдаёт угол поворота и нажатость его клавиш, т.о. единственное отличие бота от реального игрока — персонаж игрока получает ввод от клавиатуры и мыши, а персонаж бота получает ввод от ИИ. Помимо беготни по графу вейпоинтов бот также умеет реагировать на объекты: валяющиеся пушки и пауэрапы, других ботов и некоторые пули. Причем бот реагирует на эти объекты тогда и только тогда, когда они находятся в зоне его видимости: в пределах его «камеры» (как у игрока) и не отгороженные стенами.
В следующем видео демонстрируется ИИ бота по имени Лягуха в поединке с другими ботами на большой карте:
| Алгоритм | Время, мс |
|---|---|
| Генерация текстур частиц | 280 |
| Генерация текстур крови | 190 |
| Генерация реки лавы | 700 |
| Генерация остальной карты | 630 |
| Создание графа | 210 (720) |
| Всего: | 2010 (2520) |
В скобках указано время без использования хеша для вейпоинтов. Этот хеш служит для быстрого поиска вейпоинтов рядом с данным в некоторых алгоритмах построения графа. Без этого хеша в этих алгоритмах перебираются вейпоинты со сложностью O(n 2 ).
Сетевая часть
Сервер написан на node.js с использованием WebSocket. Весь сервер состоит из трёх частей: master-server — http-сервер, раздаёт статику; game-server — соединяется с мастер-сервером и невидим для пользователя, владеет игровыми комнатами; игровая комната — именно к ней коннектится пользователь по веб-сокету, там бегают другие игроки и боты.
При разработке серверной части был применён подход с использованием фейксокетов. Что это такое? Фейксокеты — это два объекта в клиентской части с интерфесами настоящего клиентского и серверного сокета. Они эмулирует работу реальных сокетов. «Клиентский» и «серверный» фейксокет (в кавычках, потому что они оба клиентские, т.е. браузерные) обмениваются данными друг с другом по средством setTimeout (в целях отладки был выбран интервал он же пинг в 30 миллисекунд). Идея в том, что настоящий серверный код можно отдать браузеру, сказать ему, чтобы он работал в режиме фейксокетов. При этом настоящий клиентский код даже не подозревает, что и сервер работает рядом с ним в браузере, он просто посылает данные в сокет (которым является фейксокет) и получает данные с него. Фейксокеты использовались при разработке и отладки серверного кода. Но настоящий online работает через реальные сокеты.
Даже после окончания разработки серверного кода фейксокеты не пропали зря, они остались в проекте и служат в качестве подстраховки, в случае, если игровая комната по каким-либо причинам недоступна. Как это работает? Когда пользователь заходит в игру, то может случиться два варианта: комната свободна и готова принять нового игрока, тогда ему просто отдаётся ip адрес и порт комнаты и он играет онлайн. Второй вариант: если нет мест в комнатах или все комнаты покрешались, тогда мастер-сервер говорит браузеру переходить в режим фейксокетов, также посылает ему весь серверный код (ну не весь, а только код игровой комнаты). И пользователь играет в игру с ботами исключительно локально (ну не повезло ему), при этом пользователь даже не будет знать, что он играет локально (ну это в идиале).
Фейксокеты сыграли огромную роль при разработке серверной части. Т.к. и клиент и сервер запущены в браузере — их очень легко отлаживать, также можно выводить на экран debug-render, т.е. схемотично рендерить объекты именно в тех позициях, где они реально находятся на сервере в данный момент времени. Можно играться с пингом: менять интервал в функции setTimeout, чтобы реализовать всякие предсказания и посмотреть, как они работают на разных пингах (в данном проекте, правда, не было реализовано никаких предсказаний).
- Легкая отладка — и сервер и клиент находятся в браузере
- Можно ставить любой пинг и смотреть, как будет играться при разных его значениях
- debag-render позволяет понять, как объекты выглядят прямо сейчас на сервере
- В игре должны быть боты, если нет ботов, то фейксокеты бесполезны
- Сервер должен быть написан на том же языке, что и клиент
- С ними можно отлаживать разве что логику серверного кода, но вот полную серверную картину (траффик, нагрузка на сеть, разный пинг у разных клиентов. ) они не дадут
Заключение
Помимо всего вышеперечисленного в игре также есть своя консоль, которая вызывается клавишей тильда (с командами, переменными, автодополнением и историей). Ещё есть довольно неплохой генератор ников и система событий.
Полный исходный код игры выложен на github.
Руководство по запуску (у вас должен быть установлен node.js).
Если у вас уже установлен bower, то этот шаг пропускаем, иначе:
В корне проекта выполняем две команды:
Если 80 порт у вас занят, то можно так:
В принципе, этого уже достаточно, можно зайти на localhost (ну или localhost:8800, если сменили порт) и там уже будет игра, правда локальная через фейксокеты. Если нужен честный онлайн, то в другой консольке выполняем:
Теперь можно зайти в игру не только с этого компьютера, но и с любого другого, просто указав в адресной строке ip мастер-сервера. Чтобы узнать локальная ли игра, нужно вызвать консоль игры и выполнить команду status. Ещё одна интересная команда spectator nick, где nick — имя игрока, тогда камера переместится на этого игрока. По умолчанию будет сгенерирована большая карта на 110 игроков. Чтобы генерировать другие карты, нужно выполнить:
Здесь не опечатка, количество дефисов именно такое.
Эта команда сгенерирует маленькую карту, которая описывалась в этом посте. Поддерживаются следующие size: 0 — маленькая карта, 1 — средняя и 2 — большая карта (по умолчанию).
Запускать лучше всего в браузере chrome, в других браузерах не гарантируется корректная работа.
Программы для создания игр без программирования
В этой подборке собраны лучшие конструкторы для создания 2D и 3D игр. С их помощью легко создать шутер, стратегию, квест, гоночный симулятор без навыков программирования.
Программы для создания квестовых игр
Начнем наш рейтинг с тектовых программ для квстовых игр.
Игровой редактор для создания квестов, приключенческих игр и интерактивной фантастики. Программа с открытым исходным кодом предоставляется бесплатно.
После запуска редактора рекомендуется просмотреть созданные другими пользователями игры. Во вкладке «Play» можно загрузить квест из каталога. Программа автоматически скачает игру и предложит ее запустить. Разобравшись с механикой, разработчик может приступить к созданию своего проекта во вкладке «Creat», на выбор предлагается текстовый квест или интерактивная книга.
Доступные инструменты: создание комнат, объектов, работа со скриптами, плеер для отображения кнопок, иконок, интерактивных окон, настройка интерфейса, выбор цвета и размера текста, шрифта. Меню игрока: количество очков здоровья, денег, вещей в инвентаре и других объектов.
Интерфейс программы переведен на английский и немецкий язык. Софт работает только под управлением операционной системы Windows. Скачать дистрибутив на жесткий диск можно на официальном сайте. Пользователи других OS могут воспользоваться онлайн-версией продукта, доступной после регистрации.