Как стать автором
Обновить

Движок для игры от первого лица в 265 строках Javascript

Уровень сложностиСложный
Время на прочтение6 мин
Количество просмотров26K
Всего голосов 61: ↑60 и ↓1+76
Комментарии36

Комментарии 36

Для этого мы воспользуемся приёмом под названием «бросание лучей» (raycasting). Возможно, вы видели примеры такой техники в играх Daggerfall и Duke Nukem 3D,

В Duke Nukem 3D raycasting? Не порталы?
Raycasting есть в Wolfenstein 3D.

НЛО прилетело и опубликовало эту надпись здесь

Build определённо портальный движок. Но заблуждение, что это рейкастер, довольно распространено.

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

Часов

А ничего, что с тех пор прошло -цать лет и изначальная версия была на 110 страниц, а текущая спека на 840?

И даже для первой версии это мягко говоря преувеличиние, что он написан на коленке.

https://www.ecma-international.org/publications-and-standards/standards/ecma-262/

Разве не js описали за 10 дней?

За 9. А последний день отдыхали.

А лично я каждый раз поражаюсь, сколько электричества портит бесполезной работы (то есть не относящейся непосредственно к решаемой задаче) — вроде выделения-освобождения памяти, создания-уничтожения объектов и т.п. — выполняет JS (да и любой другой интерпретируемый язык).

Эта работа необходимая, я бы даже сказал неизбежная.
Просто в одних языках ради максимальной производительности ее делает сам программист, тратя свое время и силы, а в других ему работу облегчили и это делает интерпретатор языка, расплачиваясь большим потреблением ресурсов.
Оба подхода правильные - разным задачам, разные инструменты.

В вашу дихотомию не укладывается Rust.

в одних языках ради максимальной производительности ее делает сам программист, тратя свое время и силы

Как говорил один мой знакомый, "это только первые двести раз — а потом привыкаешь, втягиваешься, и делаешь всё, что надо, на автомате".

А потом мы читаем в CVE про ошибки двойного освобождения или ловим утечки.

А потом мы читаем в CVE

А ведь я говорил — два стека надо делать было! Дык нет — запихали пользовательские данные вперемешку с адресами возврата — теперь разгребают.

Тогда уж надо было делать 2 памяти: для кода и для данных. И даже тогда будут баги, когда в ОС передали не тот указатель и в итоге данные утекли в код.

Тогда уж надо было делать 2 памяти: для кода и для данных

Эту Вашу идею уже украли!

Не грустите сильно по поводу JS - ребята из Гугла и мозилы сделали довольно много чтобы не считать его "интерпретируемым" в чистом виде, да и нет в нормально написано коде лишних созданий-уничтожений объектов, т.к. передача объектов по ссылке.
А бэкенды-перекладыватели-json'ов сам скотч велел писать на JS.
Впрочем по поводу зря сожженных ресурсов я лично впадаю в уныние от косоруких программистов, которые не умеют делать фронтенд без реакта, и этот самый реакт теперь на каждом втором сайте отжирает память и CPU просто так.

Шаблонное обучение выпускает шаблонных программистов, шаблонные программисты не способны творить новое и понимать как всё работает, как следствие оптимизировать. К сожалению современным миром управляют деньги, кто платит, тот и заказывает. А на реакте можно выпустить говнецо гораздо быстрее, чем хороший программист постарается. Больше всего бесит во всём этом, что стадо шаблонщиков считает себя программистами и просят за это хорошие зарплаты

Реакт весит пяток килобайт. Даже если обвесить его всеми нужными для написания полноценного фронтенда кода, сам реакт будет весить пусть килобайт 15.

Память отжирает не реакт, а те кто не умеют писать нормальный код без лишнего усложнения, но при этом с удовольствием тянут в проект всякий хлам типа UI-кита на пару мегов и забивают при этом даже на минимальную настройку webpack'а.

После коленок там прошло четверть века профессиональной и интенсивной разработки.

жаль только браузеры жрут как не в себя . Поэтому создавать что-то серьезное для веба чуть менее чем хочется.

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

Интересно, насколько сложно добавить объекты и анимированных персонажей, чтобы корректно отрисовывались даже если из-за угла стены видна только их часть?

Подумываю сделать такой клиент для своего сетевого проекта.

В таких рейкастерах объекты рисутся столбцами, как и стены, как бы по Z буферу, только не он не попиксельный, а постолбцовый - таким образом легко решается проблема отрисовки объектов за углом стены. Главная проблема с объектами в рейкастере в том, что они отдельная от стен сущность, с совсем другой математикой и принципом работы (типа классического 3D, крутим точки в мировых координатах согласно камере, проецируем в экран), и получается, что по сути нужно подружить два разнородных движка. Поэтому многие, кто пробует делать рейкастер, останавливаются на стенах. Не то, чтобы это было сложно, просто внезапно оказывается, что всё, что было изучено и понято для отрисовки стен, к объектам отношения не имеет, и надо понимать заново.

А если нужна ещё и текстура пола-потолка - то это ещё одна отдельная история, а если разновысотность и диагональные стенки - то третья, а если карта не по сетке - то четвёртая. И все эти разнородные вещи нужно совмещать. В этом смысле полигональный рендер типа Quake устроен значительно проще.

Круто! Спасибо за развернутый ответ

они отдельная от стен сущность, с совсем другой математикой и принципом работы

а нельзя тут использовать спрайтовую логику? т.е. просто взять картинку с прозрачным фоном, отмасштабировать её с учетом дальности, обрезать если торчит из-за стены и ляпнуть на вычисленное место? Еще бы конечно здорово, если поддерживались гифки, можно было сразу анимированные спрайты фигачить, но это больше вопрос к элементу canvas.

А если нужна ещё и текстура пола-потолка

Да текстура пола не помешала бы. Возможность замостить разными плитками.

 а если карта не по сетке - то четвёртая

С этим у меня, к счастью, проблем нет. У меня всё на квадратной дискретной сетке. Сейчас у меня игра отрисовывается как вид сверху, очень удобно реализовать. Если кто-то поворачивается - просто крутануть картинку. Здесь получается нужны разные спрайты для этого. Было бы конечно круто к клиенту с видом сверху добавить клиент вот с таким псевдо-3Д. Одна игра с такими разными представлениями, просто разрыв шаблона

С объектами в рейкастере две проблемы. Более простая - как рисовать. Это по сути и есть спрайтовая логика, только спрайт рисуется не сразу весь целиком, а столбцами в один пиксель шириной. В зависимости от глубины спрайта в сцене (на весь спрайт одна глубина) и глубины уже нарисованной в этом столбце пикселей стены можно определить, нужно ли рисовать столбец спрайта (если стена ближе спрайта, он за ней, его не видно). Более сложная проблема - что и где рисовать. Найти объекты на карте трассировкой лучей не получится, если конечно они не двигаются по клеткам, а плавно. Надо спроецировать их в экран, то есть каждый спрайт повернуть на угол камеры, сделать 3D проекцию, отсечь лишние спрайты (хотя бы за спиной), отсортировать оставшиеся по дальности, и тогда уже рисовать - всё как в традиционных 3D движках.

Найти объекты на карте трассировкой лучей не получится, если конечно они не двигаются по клеткам, а плавно

К счастью у меня всё дискретно. Объекты находятся на клетках и не могут занимать промежуточных положений. По сути - это разновидность стен, только прозрачные для дальнейшего распространения взгляда. Думаю, это сильно упрощает задачу

Надо ещё правильно сделать порядок отрисовки, чтобы дальние объекты не рендерились раньше ближних

Тогда должно быть попроще. Это примерно как устроены двери и диагональные стены в подобных движках. - особый случай клетки, в которой трассировка не прекращается. Для объектов понадобится запоминать их по мере трассировки и потом рисовать в обратном порядке, чтобы они корректно накладывались друг на друга.

Спасибо, очень вдохновляюще, попробую сделать

я читал немножко

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

У меня нет ни секторов, ни порталов. Т.е. мне прийдется их как-то динамически создавать из коордиант стен, пришедших с сервера

Их надо заранее просчитать. Кстати, для карт типа Wolf-3D я как-то делал автоматическое построение порталов и секторов. Сектором там является сам квадрат сетки, а порталами его стороны.

А почему автор не сократилCos(ArcTan(x))=1/Sqrt(1+x*x)?
НЛО прилетело и опубликовало эту надпись здесь

Я-то думаю: что за стиль кода такой из прошлого? А но вон оно чё: оригинальной статье девять лет оказывается. Это, конечно, не отменяет её полезности, но всё ж

Зарегистрируйтесь на Хабре, чтобы оставить комментарий