Последние рекорды серверов
Pro Nub

Физика Glide

Опубликовано Kpoluk 17 Мар в 10:12
В статье про физику EdgeBug и JumpBug мы познакомились с такой техникой, как bounce. Название это не общеупотребительное, и в дополнение к нему мы сейчас введём ещё одно. Можно найти немало примеров сокращений, когда игрок падает с большой высоты, делает bounce о наклонную поверхность и затем ударяется о другую поверхность, получая вертикальную скорость. Причём эта поверхность как правило не является слайдом, но движение по ней очень похоже на скольжение. Таким примером может послужить сокращение на kzno_extremeblock, когда игрок ударяется о кнопку старта, затем движется на doubleduck'ах до наклонной поверхности и уже на ней происходит то самое скольжение, которое мы будем называть Glide. Попробуем разобраться в физике этого явления.

Мы уже знаем, что в PM_WalkMove выполняется трейс в направлении скорости, и если этот трейс ничего не задел, то новым положением игрока origin становится конец трейса. При переходе с горизонтальной поверхности на наклонную трейс в какой-то момент пересечёт эту наклонную поверхность, и тогда нужно, прямо как это было в PM_AirMove, с помощью вызова PM_FlyMove протянуть положение до пересечения, а затем спроецировать вектор скорости на наклонную плоскость и оставшийся путь протянуть уже вдоль плоскости. Однако на этом работа PM_WalkMove не заканчивается:


Координаты и скорости, полученные в ходе работы PM_FlyMove, сохраняются в переменные down и downvel, и производится расчёт для альтернативного перемещения: трейс на высоту ступеньки stepsize (18 юнитов) вверх, перемещение в конец трейса, вызов PM_FlyMove, ещё один трейс обратно на stepsize вниз, перемещение в конец нового трейса. Как можно догадаться, этот вариант перемещения создан для того, чтобы можно было без выполнения прыжка подниматься по ступенькам. Ну а выбор между двумя вариантами производится следующим образом:


Если трейс вниз на stepsize пересекал слайд, то выбираем первый вариант. В противном случае выбираем тот вариант, который произвёл большее горизонтальное перемещение. Причём во втором варианте вертикальная скорость берётся из первого варианта. Звучит как-то неочевидно, поэтому рассмотрим простой пример. Пусть мы движемся со скоростью 400 юнитов/с в сторону плоскости, наклонённой на 45°. Два варианта возможного перемещения будут выглядеть следующим образом:


Хотя ступенек здесь нет, выигрывает по дистанции второй вариант. В этом случае горизонтальная скорость останется прежней, а вертикальная возьмётся из расчёта первого варианта (проекция скорости на плоскость даст 400 * cos(45°) юнитов/с, а её вертикальная составляющая 400 * cos(45°) * cos(45°) = 400 / 2 = 200 юнитов/с). Далее PM_CategorizePosition обнаружит, что вертикальная скорость больше 180 юнитов/с, и выставит флаг нахождения в воздухе. На следующем фрейме вместо PM_WalkMove за нас возьмётся PM_AirMove, в которую попадёт скорость величиной 400 по горизонтали и 192 по вертикали (8 юнитов/с у нас успела забрать гравитация в лице PM_FixupGravityVelocity и PM_AddCorrectGravity). В ней вызов PM_FlyMove спроецирует вектор скорости, так что мы получим (400 + 192) / 2 = 296 юнитов/с по горизонтали и столько же по вертикали. Начиная с этого момента логика движения действительно похожа на то, что происходит на слайде: вертикальная скорость теряет 8 юнитов/с, суммарная скорость проецируется на плоскость и становится меньше по величине. Отличие здесь состоит в том, что как только вертикальная скорость окажется меньше 180 юнитов/с, PM_CategorizePosition перестанет утверждать, что мы находимся в воздухе, и управление скоростью вновь перейдёт к PM_WalkMove, которая вместе с PM_Friction будет гасить скорость намного быстрее.

Для этого же примера несложно прикинуть, какой должна быть минимальная начальная горизонтальная скорость, которая позволит перейти в glide. Исходя из условия в PM_CategorizePosition на 180 юнитов/с по вертикали, получаем 360 юнитов/с по горизонтали. Для более пологих плоскостей требуемая скорость ещё выше. Отсюда становится понятно, что обычного разгона престрейфом для перехода на glide не хватит. Однако здесь возникает следующая идея: что если попытаться сделать glide, прыгнув во время движения вверх по наклонной плоскости? Как мы выяснили в статье про физику bhop, вертикальная скорость после прыжка составляет sqrt(2 * 800 * 45) - 4 = 264.328 юнитов/с, что больше 180, так что нам остаётся лишь набрать горизонтальную скорость больше 264.328. А вот это сделать с помощью престрейфа уже не так сложно, причём после проецирования скорости на плоскость вертикальная составляющая оказывается больше, чем в момент прыжка, а значит сам прыжок станет выше. Эта техника прыжка, увеличивающая высоту за счёт перехода в glide, в своё время получила название Nannou Jump в честь джампера Nannou, который с помощью неё продемонстрировал крайне сложное сокращение на карте ae_strafers_heaven:


Здесь он разгоняется с помощью W до скорости 277 юнитов/с и запрыгивает на стену высотой 64 юнита. По расчётам для увеличения высоты прыжка на 1 юнит достаточно набрать по горизонтали примерно 271 юнит/с. Однако сложность здесь появляется во-первых из того, что не вся часть набранного престрейфа имеет нужное направление, во-вторых начальная точка прыжка находится ниже подножья стены, и в-третьих после прыжка нужно ещё и успеть долететь до стены пока вертикальная скорость не поменяла знак.

Высота прыжка может быть увеличена ещё больше, если есть возможность предварительного набора скорости. Например, последний прыжок на all1_hb_Johnny предполагает, что скорость будет набрана во время падения (высота блока перед финишем согласно надписи равна 65 юнитам):


Впрочем, последний прыжок здесь можно сделать и альтернативным способом с помощью weirdjump, тут уже кому как удобнее.