Срезаем углы!

Положу сюда перевод моей же статьи которую я написал для блога ребятам из Mega Cat studios.
Я не знаю как правильно назвать этот приём ни по-русски, ни по-английски, поэтому я написал первое что пришло в голову: «Smooth jump feature».
Америку, конечно, этой статьёй я не открыл, наш блог читают в основном искушенные геймдевом люди, но на правах блога почему бы и нет, более того, в тематических чатах телеграма я наблюдал что люди, неравнодушные геймдевом, задаются в том числе и этим вопросом, так что вылезу из ридонли и пографоманю немного.

Начнем издалека, с обработки столкновений, или коллизий. Немудрено, что в процессе создания игры, программист должен позаботиться об этом, наверное, в первую очередь. Это необходимо для того, чтобы игровой персонаж как минимум «чувствовал под ногами землю».
Коллизии — необходимая штука в каждой игре. Если мы упраздним их в Super Mario bros, Марио не сможет разбивать эти замечательные кирпичные блоки, он просто будет пролетать сквозь них. Он не сможет даже бегать по земле, потому что без обработки коллизий провалится сквозь неё в адъ.
Если бы в игре Bomber Man не обрабатывались коллизии персонажа и его врагов, Бомбермен также проходил бы сквозь стены, и не мог бы прятаться за ними от врагов. Короче, коллизии — маст хев.

Итак, в большинстве случаев персонаж вписывается в прямоугольник ABCD:



Понятно для чего? Объясню. Наша цель — не допустить того, чтобы любая из этих точек пересекала «сплошные» блоки, их которых состоит карта уровня, это стены, потолок, пол, словом, всё, что должно препятствовать персонажу.

Коллизии AC и BD не позволяют игроку «пройти» сквозь стены слева и справа соответственно. AB препятствует прыжку, если на пути прыжка расположены блоки/потолки, и, наконец, CD удерживает спрайт персонажа «на земле».

Но есть нюансы.

Допустим, игроку требуется попасть на платформу выше, через этот «разрыв» в платформе:



Поскольку наш «прямоугольник столкновений» 16 пикселей в ширине, и «дырка» в платформе также шириной в 16 пикселей, игрок должен выставить спрайт персонажа ровно под этот разрыв. Ни пикселем больше, ни пикселем меньше. Это может оказаться нетривиальной задачей, особенно если в физике передвижения заложена инерция. Если игрок будет постоянно «прицеливаться» в такие дырки, конечно, ему это быстро надоест. Поэтому такую задачу придётся как-то решать.

Первое, что пришло мне в голову — это сузить точки верхних коллизий на 5 пикселей слева и справа:



Кажись всё, можно прыгать. Но есть ещё один момент:



Как мы видим, спрайт игрока частично «перекрыл» блок. Мало того что некрасиво, так в моём случае это породило третью проблему, но не буду в это углубляться, продолжу по существу. Все эти проблемы будут решены, если в процессе прыжка выровнять спрайт персонажа в сетку 16х16 пикселей.

Так было сделано в Super Mario bros:



И в Bomber Man:



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

Поэтому сделаем то же самое.

Мы снова проверим коллизии по дальним краям нашего спрайта. Справа и слева:



Если AB пересекает блок или другой «непрозрачный» элемент фона, мы подвинем спрайт на пиксель вправо. Если же сработала коллизия CD, как на картинке, то наоборот сдвинем спрайт на пиксель влево. будем выполнять эти нехитрые действия, пока спрайт не выровняется окончательно.

Ну вот, кажется работает!



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

Как уместить информацию о полутора тысячах игровых метатайлов в пару сотен байт, как заставить боссов сражаться, как обрабатывать коллизии объектов с объектами, как сделать фон «двухслойным», перед спрайтами и за, что общего между Spectrum и Famicom — возможно это будет позже. В процессе вкатывания в несдев я не раз ломал зубы об эту консольку, и ещё далеко не все её тайны раскрыты.

Приятного геймдева! :)

8 комментариев

avatar
Ковырялся когда над клоном Contra Force заметил одну забавную штуку — коллизии с полом в этой игре проверялись только по одной центральной точке. Заметить это можно было следующим образом:

Забавно, но заметить такую казалось бы вопиющую глючность было на самом деле практически невозможно — когда игрок двигается вперед с обрыва, то он почти наверняка скрадывает это упрощение продвинувшись вперёд. Чтобы встать так как изображено на скриншоте нужно подходить к делу осознанно. Кроме того когда я воспроизвёл это упрощение у себя, то понял что оно кроме всего прочего резко упрощает движение по наклонным полам, что тоже было в оригинальной игре — когда пол наклонный, то с этими B-D надо тоже напрягать мозг, но с одной точкой всё получается довольно просто.
avatar
Ты заставил меня загрузить этот ром)
Действительно, раньше даже не придавал этому значения. Тут ещё лихо выкрутились из этого, неизвестно намеренно или случайно так вышло — опорная нога у персонажа одна, а вторая словно на заднем плане, поэтому и «узкая» коллизия выглядит вроде бы как и надо. На «раскоряченных» персонажах типа Марио из Wrecking Crew это было бы заметнее.
avatar
Вообще там если анализировать — карты все были хорошо подстроены под эту одну только центральную точку — платформы все были очень широкими как на скриншоте и узких вертикальных мест куда бы можно было упасть просто не было. Причём были места похожие на то такие как массив из переплетённых труб под конец третьего уровня, но там всё было обложено минами, прямо таки заставляло расстреливать всё заранее и мелкие подобные косяки просто терялись еще на фоне того, что квадратики-платформы сплетающие трубы были проницаемые во всех направлениях кроме сверху-вниз, что опять таки приводило к замыливанию реальности коллизий, т.к. трубы просто воспринимались частично как задний план на который и не грех немного залезть. В общем один из тех примеров когда оглядываясь понимаешь как программные решения диктовали look&feel.
avatar
Кстати, забыл спросить, как продвигается-то ремейк?
avatar
Ремейк я делать расхотел по копирайтским причинам, но возможно буду пилить самостоятельного клона без копирайтных материалов. Сплюнуть только через плечо надо. :)
Перенёс движок который накопился под GBA на SDL2 и винду/андроид и даже немного своих спрайтов нарисовал уже (человечек тут «сломанный»):

но пока только намётки. зато эксплуатируя материалы по автоматическому портированию карт из тайловых игр под свой движок чисто в рамках прикола добавил параллакс в третий уровень контры форс:
youtu.be/RBe5IZUlYnE
но это так, просто эксперименты, полноценный порт делать не вижу смысла.
avatar
Скажите, а много ли ресурсов сжирает расчет, например на NES, и можно ли улучшить графон в играх без коллизий?
avatar
В моём случае ~150 тактов на точку. У главного персонажа их 4. Также за проверкой коллизий в карту лазает каждый враг на экране, но это можно делать один раз в 8 кадров, например. В моём проекте предусмотрено 10 объектов на экране (враги, подвижные блоки, рычаги и т.д.), пока что фпс не проседал (пишу на cc65).
Вторую часть вопроса не совсем понял. Графику, разумеется, в любой игре можно улучшить, этим постоянно занимаются т.н. ромхакеры.
avatar
Ресурсоёмкость расчёта столкновений напрямую зависит от количества объектов и типа столкновений — точка-фон, либо объект-объект. Точка-фон занимает не так уж много, зависит от способа хранения карты. Как правило надо щёлкнуть банком, перевести x/y в смещение метатайла в карте, прочитать индекс, далее либо сразу прочитать табличку флагов, либо карту уточнения формы. Т.е. один расчёт и несколько LUT. Объект-объект (игрок на подвижной платформе) считать гораздо медленее, особенно если расчёт идёт в мировых координатах. Для того, чтобы стали возможными игры типа Contra, где туда-сюда летает множество пуль и бегает много врагов, там пускаются во все тяжкие, с целью уменьшения и упрощения просчёта столкновнений. Например, считают столкновения не в мировых координатах, а уже после проекции в пространство экрана — тогда расчёты становятся 8-битными и автоматически исключают вышедшие за края экрана объекты.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.