Замеры на gm_construct до и после — шесть жалоб из игры закрыты.
Исправлено по измерениям, а не по догадкам:
- vertices_of брал пересечение двух граней (прямую) и выбирал точку вне
кирпича: 1846 кирпичей из 2126 (87%) считались «без объёма», то есть
не твёрдыми. Это корень «сквозь рампу прошёл» и «падаю сквозь карту».
- clip_fraction отбрасывал грань при касании (guard `start <= limit`):
шаг 8 юнитов — стоп у стены, шаг 16 — на 8 внутрь. Guard убран,
условие `!(0.0..1.0).contains(&t)` — верно и для -0.0, и для NaN.
- Полуплоскость кирпича действовала на всю плоскость: игрок зависал
над краем площадки. Добавлен swept-bounds early-out.
- Движение шло одним общим процентом шага, из-за чего игрок «запинкой»
полз по полу. Заменено на цикл касаний TryPlayerMove (numbumps = 4).
- step_move всегда выбирал путь «вверх», а он уводил назад по склону:
игрок сползал с x = -256 до x = -1066 за 5 с. Переписано по оригиналу —
побеждает путь, ушедший дальше по горизонтали, z из движения вниз.
- stay_on_ground падал всем шагом, вминался в кирпич и выталкивался вдоль
нормали, то есть вбок по склону. Теперь зондирует вниз по 1 юниту.
- Трение было только без ввода. FullWalkMove зовёт Friction() безусловно —
именно оно удерживает игрока на рампе.
- Линейная интерполяция ускорения замедляет не хуже, чем ускоряет:
равновесие на 179 юнитах/с. Заменена квото-формула Accelerate;
sv_air_max_wishspeed = 30 действует только в воздухе.
Замер на настоящей карте (real_map_movement, --ignored):
скорость 165 -> 224,9 (среднее с разгона; Source 250)
дёрганье назад 0,00 юнита за 3 с
прыжок 42,7 юнита (Source ~45)
падение сквозь мир и проход сквозь рампу устранены
Старый real_map_player_rests_walks_and_does_not_sink требовал пройти
2000 юнитов вслепую вдоль +x, где на карте стена на x = 992 — ожидание
теста было неверно, а не игрок. Тест удалён, его корректная часть
покрыта real_map_movement.
222 теста зелёные, clippy -D warnings чист.