Как старые игры обнаруживали столкновения со стенами, полом и потолком?

Я читал об обнаружении столкновений в играх на stackoverflow и других сайтах. Многие из них говорят о BSP, ограничивающих точках, интеграции и т. Д. Однако на NES им удалось обнаружить столкновения полов и стен в играх, и мне трудно поверить, что они проделали много вычислений для обнаружения столкновений со стенами.

Я предполагаю, что мой вопрос: учитывая уровень, состоящий только из плиток, как они обнаруживают столкновения со стенами и полом в таких играх, как Mario и Megaman, у которых была небольшая вычислительная мощность?

  • Проследили ли они путь движения и определили ближайшую соединительную плитку? (немного поисков) (априори)
  • Они определили столкновение с полом, а затем выяснили, как лучше всего отрегулировать персонажа? (posteriori) Это рискованно с переменными временными шагами, вы могли бы перепрыгнуть через плитку, если бы вы были достаточно быстры. Хотя я предполагаю, что временные интервалы игр NES были синхронизированы с частотой обновления телевизора.
  • Всегда ли гравитация влияет на вашего персонажа, когда вы находитесь на земле? Или вы просто «выключаете» его, когда твердо настроены ходить по плитке? А как насчет того, чтобы спуститься с края обрыва? В противном случае вам понадобится какой-то способ определения плитки под вами.
  • Если вы столкнулись с плиткой, могли бы вы просто найти край этой плитки и переместить своего персонажа в сторону от нее (в зависимости от направления движения)?
  • а как насчет наклонных плиток, как в super metroid и mario?
  • А как насчет «платформ», где вы можете перепрыгнуть через дно и приземлиться наверху. Как бы вы справились с столкновениями с этими плитками, если бы делали это «апостериори»?

Я написал код столкновения, который в основном является «априорным», поскольку он ищет первую плитку, по которой вы попадете в определенном направлении. Мне просто интересно, есть ли способ лучше. (возможно, просто используя обнаружение столкновений постфактум)

например, код для проверки столкновения плиток при движении вниз (я проверяю вертикальное, а затем горизонтальное движение):

  def tile_search_down(self, char, level):
        y_off = char.vert_speed
        assert y_off > 0

        # t_ are tile coordintes
        # must be int.. since we're adding to it.
        t_upper_edge_y = int( math.ceil((char.y+char.h) / self.tile_height ) ) #lowest edge
        while (t_upper_edge_y*self.tile_height) < (char.y+char.h+y_off): # lowest edge + offset

            t_upper_edge_x = int( math.floor(char.x/self.tile_width) )
            while (t_upper_edge_x*self.tile_width) < (char.x+char.w):

                t_x = t_upper_edge_x
                t_y = t_upper_edge_y 
                if self.is_tile_top_solid(t_x, t_y, plane):
                    char.y = t_y*self.tile_height - char.h
                    char.vert_speed = 0.0
                    char.on_ground = True
                    return

                t_upper_edge_x += 1
            t_upper_edge_y += 1

        char.y += y_off

person Nick Sonneveld    schedule 15.07.2009    source источник


Ответы (4)


В играх эпохи NES, о которых вы говорите, все было в 2D. Уже одно это упрощает многие вещи.

Некоторые машины той эпохи (особенно с аппаратными спрайтами, такие как Commodore 64) имели аппаратное обнаружение коллизий. Большинство игр, которые не полагались на аппаратное обнаружение столкновений, использовали либо ограничивающую рамку, либо маску совпадения (1-битное растровое изображение спрайта).

В любом случае обнаружение столкновений обычно выполнялось «апостериори», за исключением особых случаев, таких как границы мира. В некоторых играх действительно были ошибки, из-за которых слишком быстрое движение при ударе по чему-то могло заставить вас пройти через это. (Фактически, обзоры игр начала 80-х часто комментируют, насколько точным было обнаружение столкновений.)

Для платформеров вы обычно проверяете, "заземлен" ли персонаж, прежде чем применять гравитацию.

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

person Laurence Gonsalves    schedule 15.07.2009

Здесь есть статья, в которой подробно рассматривается программирование "платформенной игры" для Nintendo Entertainment System (NES).

Возможно, я неправильно искал в Google, потому что я не наткнулся на эту статью раньше.

person Nick Sonneveld    schedule 17.07.2009

Для таких игр, как Super Mario World (SNES), игра сохраняла уровни в формате памяти, что позволяло легко взять местоположение Марио X / Y, преобразовать его в адрес плитки, а затем сразу же проверить плитки вокруг этого адреса. Поскольку уровни всегда имели фиксированную ширину (хотя область, которую вы могли просматривать, варьировалась), это упростило управление адресацией, поскольку она всегда была фиксированным смещением от позиции Марио, например Адрес + 1 для плитки рядом с Марио, Адрес + 0x300 для плитки под ним и т. Д.

person Sukasa    schedule 15.07.2009
comment
Я должен отметить, что после нахождения плитки Mario World использовала таблицу поиска функций для обработки столкновений плиток, что означало, что каждая плитка выполняла только тот код, который она хотела выполнить. - person Sukasa; 15.07.2009

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

Например, в Super Mario Bros. столкновение с врагами проверяется только через каждый второй кадр. Столкновение с флагштоком конца уровня происходит только один раз в 27 кадров. Существует также ограничение на максимальное количество объектов, проверяемых на столкновения, что, как известно, позволяет вам пройти через некоторые атаки браузера в конце игры, не умирая.

Другой пример - перенос Gradius на PC Engine. Вместо того, чтобы использовать более дорогостоящее обнаружение попадания в ограничивающую рамку, он использует систему тайлов. Каждый объект сокращается до номера плитки, состоящего из позиций X и Y, округленных до кратного 8 и объединенных в одно число. Если два объекта занимают один и тот же тайл 8x8, считается, что они столкнулись. Он менее точен, но имеет тенденцию благоприятствовать игроку, поэтому представляет собой приемлемый и интересный компромисс.

person user11567957    schedule 29.08.2019