Как я делал 2D-платформер и что пошло не так, или несовершенство кожаных мешков

 Публичный пост
12 декабря 2022  1840

Я - один из тех людей, которые стали программистами потому-что любили компьютерные игры, а теперь получают 300кк/сек за перекладывание джисонов и спрашивают себя "госпади, зачем это всё?!".

Но, хоть это (слава богу) и не стало профессией, я до сих пор люблю видеоигры. И, следствием из этого, у меня есть интерес и желание делать что-то своё. Так в этом году я вкатился в новое хобби - геймдев.

(Инди-студия за неделю до релиза, aka почему я рад что это не моя профессия)
(Инди-студия за неделю до релиза, aka почему я рад что это не моя профессия)

Геймдев, а точнее инди-разработку, очень легко романтизировать: "Вот ты такой классный, придумал интересную идею для игры, сел да и сделал". Творчество, самовыражение, ляпота! На деле оказалось, что геймдев это постоянный поиск решения проблем о существовании которых ты час назад даже не подозревал.

Что для меня стало открытием - часто проблема с игрой находится за её пределами. Как говорили мудрые старцы, "проблема между монитором и креслом". О таких проблемах и пойдёт речь ниже.

Спойлер: Люди - не роботы, и не могут идеально подавать команды в видеоигре

(ещё одна область где бездушные машины потеснили человеков)
(ещё одна область где бездушные машины потеснили человеков)

Делаем 2D-платформер мечты

Пару недель назад я начал делать очередной всратый 2D-платформер (для меня - первый).

Начал с идеи: "обычных платформеров уже миллион, хочу чтобы мой отличался на уровне механик. Пусть у моего героя будет длииинная палка, и платформинг будет происходить с её использованием."

(Качество концепт-арта - пруф что я бэкендер а не художник)
(Качество концепт-арта - пруф что я бэкендер а не художник)

Сказано - сделано! Создал проект, накидал полигонов в качестве тестовой площадки, научил бездушную машину слушаться команд с клавиатуры:

  1. Можно ходить влево-вправо
  2. Если стоишь на земле или на палке, то можно прыгать
  3. Если ты уже в воздухе, то нельзя прыгать
  4. Если ударить палкой об стену, то отскочишь от неё
  5. Если ударить палкой об пол, то запрыгнешь на палку

Вроде всё готово, заходим тестировать иии... Всё плохо! Часть нажатий игрока теряется или игнорируется, прыжки от стен не всегда срабатывают, прыгать между двумя стенами чтобы забраться наверх практически не возможно. Что же пошло не так?

Прыжки с края платформы

Симптом: При прыжке с края платформы игрок иногда "соскальзывает" вместо того чтобы прыгнуть

Диагноз: Игрок пытается нажать прыжок в самый последний момент, и иногда делает это позже чем надо

(таймлайн или зарисовка платформы, на ваш выбор)
(таймлайн или зарисовка платформы, на ваш выбор)

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

Для этой проблемы есть фикс - можно разрешить игроку прыгнуть если он только-только начал падать. Игрок не заметит этого (если не будет специально вглядываться), а удобство прыжка с платформы сильно вырастет.


(обычно тут всего пара кадров в которые можно прыгнуть, но для наглядности я увеличил)

Это одна из самых известных проблем такого типа в платформерах, и её почти всегда решают именно так. Даже смешное название придумали - coyote time. Да, это в честь того самого койота который не сразу понимал что он висит в воздухе.

(тот самый момент, когда в хорошем платформере ещё можно прыгнуть)
(тот самый момент, когда в хорошем платформере ещё можно прыгнуть)

Прыжки с палки

Симптом: Не всегда работает прыжок с палки, вместо этого иногда персонаж просто "падает" с палки на землю

Диагноз: Иногда перед нажатием кнопки "прыжка" игрок отпускает кнопку "удара", из-за чего игра решает что игрок хочет слезть с палки

(бездушная машина осуждает твою неспособность нажать вторую кнопку, не отпустив первую)
(бездушная машина осуждает твою неспособность нажать вторую кнопку, не отпустив первую)

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

Прыжки от стен

Симптом: При прыжках от стен иногда тыкаешь не в ту сторону в которую хотел

Диагноз: Игрок хочет отскочить от стены и сразу после этого изменить направление движения стиком, иногда в этих двух действиях путается порядок

(спасибо, мозг, хорошо скоординировал)
(спасибо, мозг, хорошо скоординировал)

Тут уже проблема чуть более серьёзная, приходится думать.

Во первых, почему игрок хочет сразу развернуться? - Потому-что в воздухе можно ускоряться в нужном направлении (это платформеры, тут так принято) и игрок хочет преодолеть максимальное расстояние. Тут можно полечить необходимость идеально разворачиваться, если зафиксировать скорость отскока от стены на долю секунды (чтобы у игрока было это время изменить положение стика).

Во вторых, осталась сама проблема что игрок меняет направление раньше удара. Самое простое решение которое я нашёл - смотреть не менял ли игрок недавно направление, и если менял - то пробовать оттолкнуться от стены за спиной.

Input buffer

Симптом: Иногда часть нажатий пропадает, например когда пытаешься прыжками двигаться по земле или прыгать на палке

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

Вот эта проблема точно есть почти во всех видеоиграх - на экране персонаж совершает действия, а игрок пытается сделать что-то сразу после них. Например, комбо-удары в любом файтинге. Клиент Игрок всегда прав, и если он нажал на кнопку - значит он что-то хотел.

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

В моём прототипе это виднее всего в двух местах - цепочка прыжков по земле, и прыжки с палкой. В первом случае ждём приземления на землю, во втором случае ждём пока залезем на палку перед прыжком.

Последствия костылирования

Из хорошего - в игру наконец-то стало возможно играть! Бездушная машина уступила и пытается делать то что хочет пользователь, а не то что он подаёт на вход.


(совершенно точно первый дубль и не перезаписывал много раз)

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

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


(так и рождаются техники для спидранов)

Вместо заключения

В итоге пока делал все эти фиксы пришёл примерно к такой мысли:

Ты не можешь изменить человека, поэтому остаётся только менять его окружение

То есть чтобы игра казалась честной игроку, нужно сломать её таким образом чтобы скомпенсировать ущербность игрока.

Интересно, в каких ещё местах приходится применять такую логику?

23 комментария 👇

Желаю тебе никогда не разрабатывать игру с вероятностями и рандомом, потому что окажется что там тоже надо накостылять прям очень много, чтобы игроку было "честно" по ощущениям

  Развернуть 1 комментарий

@captaingim, кстати да, Сид Мейер в своей автобиографии «Жизнь в мире компьютерных игр» писал как раз об этом.

  Развернуть 1 комментарий

@captaingim, на икском вон так и бухтят, хотя там и так в пользу игрока накручено

  Развернуть 1 комментарий

@PmJGRNOozIJestBI, Да-да, они такие "Ну самый сложный режим полная хуйня несправедливая", а в сложном просто нет подкрутки

  Развернуть 1 комментарий
Ilya Zverev Главный по картам 14 декабря 2022

Напомнило раздел «Player Forgiveness» из ролика про движение в игре Celeste:

  Развернуть 1 комментарий

Кайф статья, нет желание на DTF запосить?

  Развернуть 1 комментарий

@IgorAlentev, не сижу на DTF, так-что и интереса постить туда что-либо нет

  Развернуть 1 комментарий

@festinuz, Тогда мб kkknights?

  Развернуть 1 комментарий

В первый раз о них слышу, но судя по гуглу там у сообщества другие интересы

  Развернуть 1 комментарий

@festinuz, а блин, с бота не отридачилось) Имел в в иду https://kknights.com/ (с двумя k)

Или на хабр)

  Развернуть 1 комментарий

😱 Комментарий удален его автором...

  Развернуть 1 комментарий

@VBodrov, Так я же там уже пол года (и ноль геймджемов)

Но спасибо за приглашение!)

  Развернуть 1 комментарий

😱 Комментарий удален его автором...

  Развернуть 1 комментарий

Спасибо за рассказ! А у меня сразу вопрос вдогонку к последней фразе (которая тоже вопрос про «в каких местах применяется такая логика»): неужели до сих пор нет приличных библиотек для платформеров, которые бы всё это уже делали? Чтоб только задать допуски типа времени койота и т. п., сконфигурировать граф состояний — и игра получала бы готовые сигналы?

  Развернуть 1 комментарий

@skalbagge, Наверняка есть, но сам не гуглил.

В целом для разных жанров есть почти коробочные решения, например GameMaker Studio для top-down 2D игорь. Там прям визуальный интерфейс и просто накликиваешь что хочешь, и при этом на нём можно делать полноценные проекты (привет, Hotline Miami)

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

  Развернуть 1 комментарий

@IlyaZverev,

Celeste и Spelunky — это два обязательных must read/must watch по реализацию платформеров и procedural generation. Благо, про них много рассказано и показано (в одном из комментариев есть ссылка на Celeste).

Еще полезные:

Math for Game Programmers: Building a Better Jump

Math for Game Programmers: Juicing Your Cameras With Math

  Развернуть 1 комментарий

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

  Развернуть 1 комментарий

Вообще это уже где-то шестой мой "проект мечты", так-что я уже научился наслаждаться процессом :)

Интересно, что с каждой итерацией масштаб "хотелок" всё меньше, а получается в среднем лучше

Я честно хотел вкатываться через геймджемы, но попробовал и не вкатился. Может пока не хватает навыков чтобы за два дня собрать что-то готовое, а может просто формат с кранчем не нравится.

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

Для меня тут большим вдохновением служит канал вот этого чувака:
https://www.youtube.com/@SebastianLague

Очень нравится, что у него каждое видео - какое-то приключение в мир геймдева, полный удивительных и интересных вещей.

  Развернуть 1 комментарий

@festinuz, бывают джемы и не на 2 дня, а на неделю или месяц).

Мне нравятся, джемы с особенностями, например, LowRez - где надо игру с расширением 64х64 пикселя сделать, есть джем где надо игру сделать по обложке готовой и т.п.

Это просто помогает сгенерировать много разных идей, найти людей с кем работать приятно, издателей встретить, ну и может одну из игр потом довести до релиза.

  Развернуть 1 комментарий

Сделали вот такую штуку, чтобы тыкать в разные модификаторы передвижения в платформерах
https://gmtk.itch.io/platformer-toolkit

  Развернуть 1 комментарий

Интересно, в каких ещё местах приходится применять такую логику?

Не знаю как в играх, но мы один раз делали свою реализацию многоуровневого выпадающего меню для движка интернет-магазина.

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

И тоже, куча таймингов и замеров скорости движения мыши, чтобы не было случайных переключений. В итоге после реализации меню решили, что такими темпами будем лет 5 делать весь магазин и решили забить.

  Развернуть 1 комментарий

Как раз про эту проблему есть классная статья на Хабре из далёкого 2013 года, в которой рассказывается как эту проблему решают обычно и как её интересно решил Амазон:
https://habr.com/ru/post/171905/

  Развернуть 1 комментарий

Концепт напомнил Getting Over It от которой хотелось все вокруг уничтожить :)

  Развернуть 1 комментарий

А ты знал про Getting over it когда придумывал механику?

  Развернуть 1 комментарий

@alexdenis, Да, знал, но она не вдохновляла дизайн никак :)

Getting over it специально сделан чтобы быть неудобным, а я целился в традиционный платформер с какой-то интересной механикой сверху

  Развернуть 1 комментарий

😎

Автор поста открыл его для большого интернета, но комментирование и движухи доступны только участникам Клуба

Что вообще здесь происходит?


Войти  или  Вступить в Клуб