Беннетт Фодди раскрыл секрет механики молота в Getting Over It
Фундаментальный элемент механики игры Getting Over It with Bennett Foddy — это молот главного героя. Именно этот инструмент служит основным средством взаимодействия с миром: с его помощью персонаж перемещается, преодолевая горы и абстрактные нагромождения объектов. Недавно разработчик проекта решил приоткрыть завесу тайны и поделился техническими деталями реализации этой системы.
Reddit представляет собой экосистему сообществ, именуемых подреддитами. Платформа придерживается идеологии пользовательского контента, позволяя каждому не только создавать публикации, но и запускать собственные тематические площадки для обсуждений. С момента введения открытой регистрации сообществ в начале 2008 года пользователи активировали более 100 тысяч подреддитов, охватывающих всё — от массовых интересов до узкопрофильных ниш.
Типичный пример узкоспециализированного сообщества — /r/howdidtheycodeit. Судя по названию, этот форум создан для начинающих разработчиков, которые стремятся разобраться, как реализовать ту или иную «магическую» программную механику. Участники совместно анализируют алгоритмы, предлагают варианты прототипирования и дискутируют о возможных архитектурных решениях.
Популярность сообщества лучше всего иллюстрируется его топовыми постами. До недавнего времени лидерство удерживала публикация о нестандартном эффекте WebGL, позволяющем отслеживать положение окон браузера на рабочем столе. Эксперты в комментариях сошлись на том, что это результат синергии window.getScreenDetails() и localStorage, обеспечивающего синхронизацию данных между окнами, либо комбинация получения системных координат окна и событий storage.
Однако лидеры рейтинга сменились: на вершину поднялся вопрос реддитора о механике молота в Getting Over It. Неожиданно для всех в дискуссию вступил сам создатель игры, Беннетт Фодди.
Фодди известен как автор QWOP — проекта, где управление ногами бегуна превращалось в издевательски сложный процесс. Браузерная версия 2008 года обрела феноменальную популярность: к 2011 году сайт разработчика насчитал 30 миллионов посещений. Позже Фодди экспериментировал с похожими концепциями в CLOP (симулятор единорога) и GIRP (скалолазание), пока не довёл эту идею до абсолюта в Getting Over It, где игрок управляет обнажённым мужчиной по имени Диоген, запертым в котле.
В то время как ранние игры требовали филигранной работы с клавиатурой, Getting Over It полностью полагается на мышь или тачпад. Управление положением молота через мышь позволяет совершать резкие махи, но из-за высокой чувствительности и физической модели развитие мышечной памяти требует колоссального терпения.
Беннетт Фодди не просто дал совет — он выложил фрагмент исходного кода функции fixedupdate, подробно описав внутреннее устройство системы. По словам автора, он сам уже не помнит всех нюансов реализации, но суть такова: обратная кинематика рук не влияет на физику напрямую; молот приводится в движение вращательными и поступательными сочленениями, а всё управление базируется на принципах простого пропорционально-дифференциального регулятора.
Vector2 mw = (Vector2)fakeCursorRB.position;
//this value ranges between 0.1 and 0.4
mouseVelocityAverage =
Mathf.Lerp(mouseVelocityAverage, Mathf.Max(0.1f * mouseInput.magnitude, 0.001f), 0.05f) + 0.005f;
//move fake cursor - using acceleration
Vector2 newPosition = fakeCursorRB.position + mouseInput;//* mouseVelocityAverage;
//clamp to radius
float distanceToPlayer = ((Vector2) transform.position - newPosition).magnitude;
if (distanceToPlayer > 3.5f)
{
newPosition = (Vector2) transform.position +
((newPosition - (Vector2) transform.position).normalized * 3.5f);
}
Vector2 tipDelta = (Vector2) tipRB.position - mw;
Vector2 poleDir = (Vector2) (tipRB.position - hjRB.position).normalized; //hjRB is the hinge joint RB
//a dot product is used to make the rotation dominate when the mouse is perpendicular to the pole
dotProd = Vector2.Dot(poleDir, tipDelta.normalized);
posDelta = tipDelta.magnitude * dotProd;
//move back to tip head
newPosition += 0.5f tipDelta Mathf.Clamp(0.2f - Mathf.Min(mouseVelocityAverage,0.2f), 0, 0.2f);
fakeCursorRB.MovePosition (newPosition);
fakeCursorRB.velocity = (newPosition - fakeCursorRB.position);
Vector2 mwDelta = (Vector2)hjRB.position-mw;
Vector2 tDelta = hjRB.position - tipRB.position;
float angleDelta = Vector2.SignedAngle(tDelta,mwDelta); //hingeJoint2D.angle no longer works accurately
//different behavior close vs far
angleDelta = Mathf.Sign(angleDelta) Mathf.Max(Mathf.Abs(angleDelta/2f), Mathf.Abs(angleDelta angleDelta));
angleDelta *= Mathf.Clamp01 (Mathf.Abs (angleDelta) / angleEpsilon);
motor.motorSpeed = Mathf.Clamp( (angleDelta (3f) + (angleDelta - oldAngle) 0.00f) * Mathf.Pow(Mathf.Clamp01(mwDelta.magnitude/deadzone),2), -800f,800f);
hj.motor = motor;
float speedFactor = 16f - Mathf.Max(sj.reactionTorque0.008f ,5f); //had to make this stronger, no idea why
float axisBlend = Mathf.Pow(dotProd,4);
slider.motorSpeed = Mathf.Clamp(-posDeltaMathf.Abs(posDelta) speedFactor axisBlend,-50f,50f);
sj.motor = slider;
oldAngle = angleDelta;
В игре не используется системный курсор: вместо него введено «фиктивное» тело fakeCursorRB, которое накапливает относительные движения мыши и ограничено радиусом в 3,5 единицы вокруг игрока. Это решение нивелирует влияние перемещения камеры на управление персонажем. Фодди также предусмотрел «мёртвую зону» в центре вращения, где чувствительность динамически регулируется, чтобы избежать резких рывков при малых движениях.
Интересно, что физика игры работает на более высоких частотах, чем стандартная частота обновления монитора. Фодди использовал FixedUpdate с активным continuous collision detection и дробными временными шагами, так как контроллер рассчитан на очень высокие скорости вращения и перемещения. Корневой объект персонажа перемещается, но его вращение жестко ограничено, иначе реактивный момент от молота сделал бы геймплей неуправляемым.
Рукоять молота — это набор физических тел, соединённых через fixed joint 2D для обеспечения минимальной гибкости. В то же время руки персонажа реализованы исключительно через обратную кинематику: они «прилипают» к молоту постфактум, не оказывая силового воздействия на физическую модель. Моторы вращения и скольжения постоянно стремятся привести молот к цели, заданной мышью, но благодаря физическому движку и столкновениям с окружением именно эти попытки «вытягивают» котел с персонажем вверх.
На вопрос о глубоких познаниях в теории автоматического управления (ПИД-регуляторах) Беннетт ответил со скромностью: все знания были почерпнуты из университетского курса физики, который он в своё время закрыл на средние оценки, а многие параметры в итоговом коде были подобраны исключительно эмпирическим путём в процессе бесконечных экспериментов.
Создатели extraction-шутера платят игрокам реальные деньги, но списывают средства за спавн персонажа
Раскрыта реальная стоимость физических игр на фоне отказа Sony от дисков
Президент Bones объяснил причины экранизации «Брачного токсина»
Bethesda анонсировала мрачное обновление для Fallout 76 с новым тёмным контентом
Для Quake 4 выпустили отмененное дополнение The Awakening, которое восстановил разработчик
У создателей сериала «Ходячие мертвецы: Мёртвый город» появились идеи для четвёртого сезона
Звезда фильма «Планета обезьян: Новое царство» присоединилась к актерскому составу экранизации The Legend of Zelda
«Одиссея» обошла «Тёмного рыцаря» и стала самым кассовым фильмом Кристофера Нолана