Обнаружение поверхности в 2D игре? - PullRequest
4 голосов
/ 04 июня 2010

Я работаю над игрой на 2D-платформе, и мне было интересно, как лучше (с точки зрения производительности) реализовать определение поверхности (столкновение).

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

альтернативный текст http://img375.imageshack.us/img375/1704/lines.png

Я думаю, что каждый объект имеет идентификатор поверхности, по которой он ходит, чтобы легко манипулировать его положением у при ходьбе вверх / вниз.

Примерно так:

//Player/MovableObject class
MoveLeft()
{
    this.Position.Y = Helper.GetSurfaceById(this.SurfaceId).GetYWhenXIs(this.Position.X)
}

Таким образом, логика, которую я использую, чтобы обнаружить «падение / хождение по поверхности» - это простая проверка точки (нижние ноги игрока) - линия касаний (поверхность) (с некоторым приближением безопасности - допустим 1-2 пикселя над линией).

Этот подход в порядке? У меня возникли трудности с поиском материалов для чтения по этой проблеме, поэтому не стесняйтесь оставлять ссылки / советы.

Ответы [ 8 ]

3 голосов
/ 07 июня 2010

Давно поработав с 2D-платформерами на основе полигонов, позвольте мне дать вам несколько советов:

Сделать платформер на основе плитки.

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

Вы должны сделать свою геометрию мира "твердой" (вы можете избежать создания объекта вашего игрока, но лучше сделать его твердым). Под «сплошным» я имею в виду - вам нужно определить, пересекает ли * объект игрока геометрию вашего мира.

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

В Интернете есть множество инструкций о том, как проводить тесты пересечений между различными фигурами. Если вы только начинаете, я рекомендую использовать ограничивающие оси оси (AABB).

Гораздо, намного, намного, намного , намного проще сделать платформер на основе плиток, чем тот, который имеет произвольную геометрию. Поэтому начните с плиток, определите пересечения с AABB, а затем, как только вы начнете работать, вы сможете добавлять другие фигуры (например, уклоны).

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

(PS: вы можете получить потрясающие результаты только с квадратными плитками - посмотрите, например, на Knytt Stories.)

1 голос
/ 05 июня 2010

У меня были замечательные забавные времена, связанные с 2D обнаружением столкновений. То, что кажется простой проблемой, может легко стать кошмаром, если вы не планируете ее заранее.

Лучший способ сделать это в ОО-смысле - создать общий объект, например classMapObject. Это имеет координату положения и наклон. Из этого вы можете расширить его, чтобы включить другие формы и т. Д.

Исходя из этого, давайте работать с столкновениями с объектом Solid. Предполагая только блок, скажем, 32x32, , вы можете ударить его слева, справа, сверху и снизу . Или, в зависимости от того, как вы кодируете, нажимайте на него сверху и слева одновременно. Так как же определить, каким образом персонаж должен идти? Например, если персонаж ударяет по блоку сверху, чтобы стоять на нем, закодированный неправильно, вы можете непреднамеренно оттолкнуть его в сторону.

Итак, что ты должен делать? Что я сделал для своей 2D-игры, я посмотрел на предыдущее положение человека, прежде чем решить, как реагировать на столкновение. Если позиция Y персонажа + Высота выше блока и движется на запад, то я бы сначала проверил верхнее, а затем левое. Однако, если позиция Y персонажа + высота ниже вершины блока, я бы проверил левое столкновение.

Теперь, допустим, у вас есть блок с наклоном. Ширина блока составляет 32 пикселя, высота 32 пикселя при x = 32, высота 0 пикселов при x = 0. При этом вы ДОЛЖНЫ предположить, что персонаж может ударить и столкнуться только с этим блоком сверху, чтобы стоять на нем. С этим блоком вы можете вернуть ЛОЖНОЕ столкновение, если это столкновение влево / вправо / вниз , но если это столкновение сверху, вы можете указать, что если символ находится в точке X = 0, вернуть точку столкновения Y = 0. Если X = 16, Y = 16 и т. Д.

Конечно, это все относительно. Вы будете проверять несколько блоков, поэтому вам нужно сохранить все возможные изменения направления персонажа во временную переменную. Таким образом, если персонаж перекрывает блок на 5 в направлении X, вычтите 5 из этой переменной. Соберите все возможные изменения в направлениях X и Y, примените их к текущей позиции персонажа и сбросьте их на 0 для следующего кадра.

Удачи. Я мог бы предоставить больше образцов позже, но я на своем Mac (мой код на WinPC). Это тот же тип обнаружения столкновений, который используется в классических играх Mega Man IIRC. Вот видео этого в действии также: http://www.youtube.com/watch?v=uKQM8vCNUTM

1 голос
/ 05 июня 2010

Проверьте, как это делается в проекте Platformer Starter Kit XNA. В основном, плитки имеют перечисление для определения, является ли плитка проходимой, непроходимой и т. Д., Затем на вашем уровне вы получаете GetBounds плиток, а затем проверяете пересечения с игроком и определяете, что делать.

0 голосов
/ 07 июня 2010

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

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

Для обнаружения столкновений с другими объектами используйте такой же подход, но вместо логических значений используйте достаточную глубину, чтобы охватить все возможные объекты. Нарисуйте каждый объект на вторичном полностью в «цвет» его номера объекта. Когда вы читаете маску и получаете ненулевой пиксель, «цвет» - это номер объекта, на который вы попали.

Это разрешает все возможные столкновения за время O (n), а не O (n ^ 2) при вычислении взаимодействий.

0 голосов
/ 07 июня 2010

Я бы сделал это так:

  1. Строго нет линий для столкновения. Только сплошные фигуры (коробки и треугольники, может быть сферы)
  2. 2D BSP, 2D разбиение для хранения всех уровней уровней, ИЛИ алгоритм "развертки и сокращения". Каждый из них будет очень мощным. Сканирование и сокращение в сочетании с сортировкой при вставке может легко привести к тысячам потенциально сталкивающихся объектов (если не к сотням тысяч), а двумерное разбиение пространства позволит быстро получить все соседние потенциально сталкивающиеся фигуры по требованию.

Самый простой способ заставить объекты ходить по поверхностям - сделать так, чтобы каждый кадр падал на несколько пикселей, затем получить список поверхностей, с которыми сталкивается объект, и переместить объект в направлении нормали поверхности. В 2d это перпендикуляр. Такой подход заставит объекты скользить по не горизонтальным поверхностям, но вы можете исправить это, слегка изменив нормаль. Кроме того, вам придется запускать обнаружение столкновений и процедуру «отталкивания объектов» несколько раз за кадр, а не только один раз. Это должно обрабатывать ситуации, если объекты находятся в куче, или если они контактируют с несколькими поверхностями.

0 голосов
/ 05 июня 2010

Я бы порекомендовал Физика Farseer . Это отличный и мощный физический движок, который сможет позаботиться обо всем, что вам нужно!

0 голосов
/ 05 июня 2010

Не так просто создать собственный алгоритм обнаружения столкновений. Один простой пример трудности: что если ваш персонаж движется с достаточно высокой скоростью, чтобы между двумя кадрами он перемещался с одной стороны линии на другую? Тогда ваш алгоритм не успеет выполнить промежуточное действие, и столкновение никогда не будет обнаружено.

Я бы согласился с Tiendil: используйте библиотеку!

0 голосов
/ 04 июня 2010

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

...